I am using Form Classes to build the various form in my project.
In the Entity Type file, for the buildForm function, there is a secondary parameter of \"array $options\
Pass the options through the forms class __construct
method, like so:
use Doctrine\ORM\EntityRepository;
use Symfony\Component\Form\AbstractType;
use Symfony\Component\Form\FormBuilder;
class ProductType extends AbstractType
{
private $options = array();
public function buildForm(FormBuilder $builder, array $options)
{
$builder
->add('name')
->add('slug')
->add('reference')
->add('description')
->add('active_from')
->add('active_till')
->add('is_active')
->add('category', 'entity', array(
'class' => 'DEMO\DemoBundle\Entity\Product\ProductCategory',
'query_builder' => function(EntityRepository $er) {
return $er->createQueryBuilder('u')
->where('u.section = :id')
->setParameter('id', $this->options['id'])
->orderBy('u.root', 'ASC')
->addOrderBy('u.lft', 'ASC');
},
'empty_value' => 'Choose an option',
'property' => 'indentedName',
));
}
public function getDefaultOptions()
{
return array(
'data_class' => 'DEMO\DemoBundle\Entity\Product\Product'
);
}
public function getName()
{
return 'demo_demobundle_product_type';
}
public function __construct(array $options)
{
$this->options = $options;
}
}
And then you can do:
new ProductType(array('id'=>1));
Well acording to this Google Groups
"greg0ire" was right, in fact I have tried it and works perfect!!!. You said "I dont really want to go about "hacking" any of the core structure" but you end up using no the best approach.. in matter of fact, from my point of view, you end up doing what you didn't want to do.
So at the end you should do this:
at the formType
public function buildForm(FormBuilder $builder, array $options)
{
$builder
->add('name')
->add('slug')
->add('reference')
->add('description')
->add('active_from')
->add('active_till')
->add('is_active')
->add('category', 'entity', array(
'class' => 'DEMO\DemoBundle\Entity\Product\ProductCategory',
'query_builder' => function(EntityRepository $er) {
return $er->createQueryBuilder('u')
->where('u.section = :id')
->setParameter('id', $options['id'])
->orderBy('u.root', 'ASC')
->addOrderBy('u.lft', 'ASC');
},
'empty_value' => 'Choose an option',
'property' => 'indentedName',
));
}
public function getDefaultOptions()
{
return array(
'data_class' => 'DEMO\DemoBundle\Entity\Product\Product'
'id' => null
);
}
And in the controller
$form = $this->createForm(new ProductType(), $product, array('id' => $id ));
Apparently it's not with getDefaultOptions()
anymore, but with setDefaultOptions()
.
Otherwise it says
The option "my_custom_option" does not exist. Known options are: "action", "attr", "auto_initialize", ...
So, for me I had to update setDefaultOptions like this :
public function setDefaultOptions(OptionsResolverInterface $resolver)
{
$resolver->setDefaults(array('my_custom_option' => false));
// Others if needed, like in the documentation for : 'data_class' => 'VENDOR\Bundle\Entity\MyEntity', 'csrf_protection' => true
}
And then you can retrieve it in the buildForm
method
public function buildForm(FormBuilderInterface $builder, array $options)
{
$myCustomOption = $options['my_custom_option'];
}
Let me show you what worked for me
In the Controller:
$form = $this->createForm(new UsersType(), $entity, array(
'attr' => array('locationId' => $currentLocationId)));
In the FormType:
->add('location', 'entity', array(
'class' => 'Ro\RoinventBundle\Entity\Locations',
'query_builder' => function (\Doctrine\ORM\EntityRepository $er) use ($options)
{
if (isset($options['attr']['locationId']) && ($options['attr']['locationId'] != NULL))
{
return $er->createQueryBuilder('Locations')
->where('Locations.id = :param')
->setParameter('param', $options['attr']['locationId']);
}
//else do what you want
},
));
I think you're not setting them properly in the first place. You're supposed to give them as third argument to createForm()
EDIT: Here is how your form class could look:
<?php
namespace DEMO\DemoBundle\Form\Product;
use Doctrine\ORM\EntityRepository;
use Symfony\Component\Form\AbstractType;
use Symfony\Component\Form\FormBuilder;
class ProductType extends AbstractType
{
public function buildForm(FormBuilder $builder, array $options)
{
$builder
->add('name')
->add('slug')
->add('reference')
->add('description')
->add('active_from')
->add('active_till')
->add('is_active')
->add('category', 'entity', array(
'class' => 'DEMO\DemoBundle\Entity\Product\ProductCategory',
'query_builder' => function(EntityRepository $er) use($options) {
return $er->createQueryBuilder('u')
->where('u.section = :id')
->setParameter('id', $options['id'])
->orderBy('u.root', 'ASC')
->addOrderBy('u.lft', 'ASC');
},
'empty_value' => 'Choose an option',
'property' => 'indentedName',
));
}
public function getDefaultOptions()
{
return array(
'data_class' => 'DEMO\DemoBundle\Entity\Product\Product',
'id' => null
);
}
public function getName()
{
return 'demo_demobundle_product_type';
}
}
Well, it turns out, Gregoires answer was very close, but gave me and "Undefined variable" error when trying to actually but the variable into the createQueryBuilder function.
I spent a while trying to figure out why and found the issue. You have to add an extra parameter to the function in the "query_builder" option, like such:
'query_builder' => function(EntityRepository $er) use ($options) {
return $er->createQueryBuilder('u')
->where('u.section = :id')
->setParameter('id', $options['id'])
->orderBy('u.root', 'ASC')
->addOrderBy('u.lft', 'ASC');
},
The magic setting being "use ($options)". This allows you to successfully use $options['id'] in the Query Builder.