在Symfony中使用相同实体的表单事件(嵌套集)

时间:2016-02-16 19:45:14

标签: php doctrine-orm symfony-forms symfony

我正在使用Symfony 3中 stof / doctrine-extensions-bundle 的嵌套树集来创建类别层次结构。我正在尝试创建 dinamic一代提交的表单,因此当我选择一个类别时,它会向我显示子类别。

我尝试了documentation中的示例,当我使用不同的实体时,它可以正常工作,例如,当您选择省份时,在不同的实体中检索城市。

但是当我在同一个实体(使用嵌套集)中执行此操作时,我总是收到错误:必须管理传递给选择字段的实体。也许坚持他们在实体经理?

我尝试了两种方法让孩子们有选择:

$formModifier = function (FormInterface $form, Category $category = null) {

    $children = null === $category ? array() : $category->getChildren();

    $form->add('children', EntityType::class, array(
        'class'       => 'AppBundle:Category',
        'placeholder' => '',
        'em' => 'ManagerRegistry',
        'choices' => $children
    ));
};

使用query_builder:

$formModifier = function (FormInterface $form, Category $category = null) {

    $form->add('children', EntityType::class, array(
        'class'       => 'AppBundle:Category',
        'query_builder' => function (EntityRepository $er) use($category) {
            return $er->createQueryBuilder('c')
                ->where('c.parent = :category')
                ->setParameter('category', $category);
        }
    ));
};

但是我得到了同样的错误(好的EntityType使用了ChoiceType,所以我猜他们会产生相同的'选择')。

我的类别实体是doctrine扩展包中的默认实体,代码与文档中的代码相同,并且可以与不同的实体一起使用。

我怎样才能获得儿童类别?

1 个答案:

答案 0 :(得分:0)

显然它是bug并且有pull request来修复它。

我的解决方案是注入实体管理器并使用ChoiceTypes:

class SearchSubType extends AbstractType
{
protected $em;

public function __construct(ObjectManager $em)
{
    $this->em = $em;
}

public function getCategories()
{
    $categories = $this->em->getRepository('AppBundle:Category')->getRootNodes();
    return $categories;
}

public function getChildren(Category $category)
{
    return $children = $category->getChildren();
}

public function buildForm(FormBuilderInterface $builder, array $options)
{
    $builder
        ->add('category', ChoiceType::class, array(
            'choices' => $this->getCategories(),
            'choice_label' => function ($value, $key, $index){
                return $value;
            }
        ));

    $formModifier = function (FormInterface $form, $data = null) {

        if($data === null) {
            $data = new Category;
        }

        $children = null === $data->getCategory() ? array() : $this->getChildren($data->getCategory());

        $form->add('subcategory', ChoiceType::class, array(
            'choices' => $children,
            'choice_label' => function ($value, $key, $index){
                return $value;
            }
        ));
    };

    $builder->addEventListener(
        FormEvents::PRE_SET_DATA,
        function (FormEvent $event) use ($formModifier) {
            $data = $event->getData();

            $formModifier($event->getForm(), $data);
        }
    );

    $builder->get('category')->addEventListener(
        FormEvents::POST_SUBMIT,
        function (FormEvent $event) use ($formModifier) {

            $category = $event->getForm()->getData();

            $formModifier($event->getForm()->getParent(), $category);
        }
    );
}

}