在Symfony中形成具有相同实体的事件(嵌套集)


Form Events with the same Entity in Symfony (nested sets)

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

我已经尝试了文档中的示例,当我使用不同的实体时,它工作正常,例如,当您选择省份时检索一个城市,两者都在不同的实体中。

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

我尝试了两种方法来获得孩子,有选择:

$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);
        }
    ));
};

但是我得到了同样的错误(实体类型使用选择类型,所以我想它们会产生相同的"选择"(。

我的类别实体是原则扩展捆绑包中的默认实体,代码与文档中的代码相同,并且可以很好地处理不同的实体。

如何获得儿童类别?

显然这是一个错误,有一个拉取请求来修复它。

我的解决方案是注入实体管理器并使用 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);
        }
    );
}

}