Symfony 2 - how to pass data to formBuilder?

50,506

Solution 1

You can give the object you want to use in the __construct() method.

Eg :

$form = $this
    ->get('form.factory')
    ->create(new ApplyStepOneFormType($this->company, $this->ad), $applicant);

In your form type :

function __construct(\Your\Bundle\Entity\Company $company, \DYB\ConnectBundle\Entity\Ad $ad) {
    $this->company = $company;
    $this->ad = $ad;
}

And then in your form type in buildForm method :

$company = $this->company;    
$builder->add('ad', 'entity', array(
    'class' => '\Your\Bundle\Entity\Ad',
    'query_builder' => function(\Your\Bundle\Repository\AdRepository $er) use ($company) {
        return $er->getActiveAdsQueryBuilder($company);
    },
));

Solution 2

//In controller pass the value which you want to use in builder form in array like

$object = new Question();
$form->create(new QuestionType() , $object , array('sqtname'=>2,'question_type'=>2));


//In Form type class
public function buildForm(FormBuilderInterface $builder , array $options)
    {  
     //for setting data field dynamically 
  if (array_key_exists('question_type', $options) && $options['question_type'] != '') {
    $data = $em->getReference("RecrutOnlineStandardBundle:StdQuestionType",$options['question_type']->getId());
  } else {
    $data = "";
  }


  $builder->add('StdQuestionType', 'entity', array(
        'class' => 'TestStandardBundle:StdQuestionType',
        'property' => 'name',
        'empty_value' => 'Sélectionner un question type',
        'required' => true,
        'data' => $data,
        'query_builder' => function(EntityRepository $er ) use ( $options ) {
            if (isset($options['sqtname']) && $options['sqtname'] != '') {
                return $er->createQueryBuilder('sqt')
                                ->where("sqt.name!= ".$options['sqtname']);
            } else{
               return $er->createQueryBuilder('sqt');
            }
        }
    ));
 }

 public function setDefaultOptions(OptionsResolverInterface $resolver)
     {
       $resolver->setDefaults(array(
         'data_class' => 'Test\QuestionBundle\Entity\Question',
         'required' => false,
         'sqtname' => '',
         'question_type' =>'' 
       ));
     }

Solution 3

Bacteries' solution IS NOT a good one. For example, if you declare your type as service, it is impossible to pass an object to constructor.

A perfect solution is options - just pass data as option to form builder.

Solution 4

If you want to use custom query, you have to set query_builder option as follows:

use Doctrine\ORM\EntityRepository;

...

$message = new Message();

$form = $this->createFormBuilder($message)
             ->add('group', 'entity', array(
                   'class' => 'Vendor\MyBundle\Entity\Group',
                   'label'=>'Group:',
                   'query_builder' => function(EntityRepository $er) {
                       return $er->createQueryBuilder('g')
                                 ->... // whatever you want to do
                       }
                    ))
             ->getForm();

You can find more info about query builder in Doctrine manual and about options for entity in Symfony2 manual.

Solution 5

Bacteries' solution is a real good one. Just a note to save headache to other guy like me :)

In this part may I point out the use ($company) part. It was hidden by the frame and of course nothing works properly without it.

$builder->add('ad', 'entity', array(
   'class' => 
      '\Your\Bundle\Entity\Ad',
   'query_builder' => 
      function(\Your\Bundle\Repository\AdRepository $er) use ($company) {
            return $er->getActiveAdsQueryBuilder($company);
      },
    )
);
Share:
50,506
jacobmaster
Author by

jacobmaster

Updated on March 14, 2020

Comments

  • jacobmaster
    jacobmaster over 4 years

    I'm using entity choice list in my form. I want to use only specific entities (in example: only groups that user belongs to) So, in controller, I'm getting these groups, and trying to pass them into formBuider.

    Controller:

    /.../
    $groups = $em->getRepository('VendorMyBundle:Group')->getUserGroups($user);
    $form = $this->createForm(new Message($groups), $message);
    /.../
    

    so, what now? how to use it in formBuilder? how to change this line to use passed array of groups?

    ->add('group','entity',array('class' => 'Vendor\MyBundle\Entity\Group', 'label'=>'Group:'))
    

    or in the other way:

    class MessageType
    {
    /.../
      public function buildForm(FormBuilder $builder, array $options)
      {
        $builder
          ->add('group','entity',
            array(
              'class' => 'Vendor\MyBundle\Entity\Group',
              'property' => 'name',
              'query_builder' => function ($repository) {
                $qb = $repository->createQueryBuilder('group');
                $qb->add('where', 'group.administrator = :user');
                $qb->setParameter('user', $user->getId());
                return $qb;
              },
              'label' => 'Group'
            )
          )
          // Continue adding fields
        ;
      }
    /.../
    }
    

    so how can i get object $user to use in form builder? ($user represent current logged user)

  • jacobmaster
    jacobmaster almost 13 years
    Yes, i know how to use custom query, but how can i use it when i want get groups of current logged user? i must declare a container in a form type class? ex: in controller im using$this->get('security.context')->getToken()->getUser()
  • Ondrej Slinták
    Ondrej Slinták almost 13 years
    I'd recommend using ManyToOne or ManyToMany relationship here. It'd make things much easier.
  • Ondrej Slinták
    Ondrej Slinták almost 13 years
    You can possibly create constructor in type class and just push security context variables there through that in controller.
  • Ryall
    Ryall over 8 years
    Also, his solution is going to break in 3.0 as types are constructed by FQCN
  • eggmatters
    eggmatters almost 8 years
    Doesn't this defeat the purpose of an MVC application though? I thought the whole point of a framework was to obscure the data layer from the rendering layer. Like, as far as possible.
  • user1954544
    user1954544 over 7 years
    Symfony2 brokes all patterns you know... So dont be wondered. I showed solution that worked for me, sf2 is a bad mvc for developing if you want work with patterns. If you have more elegant - use yours...
  • ste
    ste almost 5 years
    This answer nowadays is wrong. You should pass such arguments as options (defined in the configureOptions method), not in the __construct of the form Type. The Type is constructed once in the container, so you get weird behaviours if you pass parameters there and you use the Type more than once in the same request with different arguments in __construct: there, you should just autowire services.