问题
Following the example as documented in the following http://symfony.com/doc/current/cookbook/form/dynamic_form_generation.html
I need to populate subcategory field according to the category selection. I don't understand why this error at /article/create:
FatalErrorException: Error: Call to a member function getSubCategories() on a non-object
the Form :
namespace Cc\HitoBundle\Form\Type;
…
class ArticleType extends AbstractType
{
private $registrationArticleListener;
public function __construct(RegistrationArticleListener $registrationArticleListener)
{
$this->registrationArticleListener = $registrationArticleListener;
}
public function buildForm(FormBuilderInterface $builder, array $options)
{
$builder
…
->add('category', 'document', array(
'label' => 'Category',
'class' => 'Cc\HitoBundle\Document\Category',
'property' => 'name',
));
$builder->addEventSubscriber($this->registrationArticleListener);
}
public function setDefaultOptions(OptionsResolverInterface $resolver)
{
$resolver->setDefaults(array(
'data_class' => 'Cc\HitoBundle\Document\Article'
));
}
public function getName()
{
return 'article';
}
}
I don't understand what is the AddNameFieldSubscriber() function in the cookbook
The Listener:
namespace Cc\HitoBundle\Form\EventListener;
…
class RegistrationArticleListener implements EventSubscriberInterface
{
/**
* @var FormFactoryInterface
*/
private $factory;
/**
* @var DocumentManager
*/
private $dm;
/**
* @param factory FormFactoryInterface
*/
public function __construct(FormFactoryInterface $factory, $mongo)
{
$this->factory = $factory;
$this->dm = $mongo->getManager();
}
public static function getSubscribedEvents()
{
return array(
FormEvents::PRE_BIND => 'preBind',
FormEvents::PRE_SET_DATA => 'preSetData',
);
}
/**
* @param event FormEvent
*/
public function preSetData(FormEvent $event)
{
$agent = $event->getData();
if (null === $article) {
return;
}
$form = $event->getForm();
$subCategories = $article->getCategory()->getSubCategories();
$this->customizeForm($form, $subCategories);
}
public function preBind(FormEvent $event)
{
$data = $event->getData();
$id = $data['event'];
$agent = $this->dm
->getRepository('CcHitoBundle:Article')
->find($id);
if ($article === null) {
$msg = 'The event %s could not be found for you registration';
throw new \Exception(sprintf($msg, $id));
}
$form = $event->getForm();
$subCategories = $article->getCategory()->getSubCategories();
$this->customizeForm($form, $subCategories);
}
protected function customizeForm($form, $subCategories)
{
}
}
And I don't understand what I have to put in customizeForm function. Please help me !! =)
回答1:
You are getting the non-object error because you are not actually creating the $article variable in your preBind or preSetData functions. It looks like you are mixing up $agent
and $article
public function preSetData(FormEvent $event)
{
//here you have $agent
$agent = $event->getData();
//here you have $article
if (null === $article) {
return;
}
$form = $event->getForm();
//here you have $article
$subCategories = $article->getCategory()->getSubCategories();
$this->customizeForm($form, $subCategories);
}
Change to:
public function preSetData(FormEvent $event)
{
$article = $event->getData();
// We can only set subcategories if a category is set
if (null === $article->getCategory()) {
return;
}
$form = $event->getForm();
//...
In customise form function you want to add the fields you need like subCategories:
//taken from the article OP referenced
protected function customizeForm($form, $subCatQueryBuilder)
{
$formOptions = array(
'class' => 'You\YourBundle\Entity\SubCategory',
'multiple' => true,
'expanded' => false,
'property' => 'THE_FIELD_YOU_WANT_TO_SHOW',
// I would create a query builder that selects the correct sub cats rather than pass through a collection of objects
'query_builder' => $subCatQueryBuilder,
);
// create the field, this is similar the $builder->add()
// field name, field type, data, options
$form->add($this->factory->createNamed('subCategories', 'entity', null, $formOptions));
}
For the query builder:
/**
* @param event FormEvent
*/
public function preSetData(FormEvent $event)
{
$agent = $event->getData();
if (null === $article->getCategory()) {
return;
}
$form = $event->getForm();
//Something like
$category = $article->getCategory();
$subCatQueryBuilder = $this->dm
->getRepository("YourCatBundle:Subcategory")
->createQueryBuilder("sc")
->join("sc.category", "c")
->where("c.id = :category")
->setParameter("category", $category->getId());
$this->customizeForm($form, $subCatQueryBuilder);
}
来源:https://stackoverflow.com/questions/15968415/symfony2-dynamic-forms-mongodb