Symfony 2.7:EntityType - 强制查询构建器中没有结果

时间:2018-02-21 12:11:11

标签: php symfony symfony-forms symfony-2.7

我没有找到解决问题的帖子,希望它不会重复。

在Symfony表单中,我声明了一个实体字段。

$form->add($builder->getFormFactory()->createNamed(
    'cert_folder_product_factory',
    new EntityMultipleType(),
    null,
    array(
        'label' => '',
        'mapped' => false,
        'class' => 'ProductsBundle:ProductFactory',
        'empty_value' => '',
        'auto_initialize' => false,
        'required' => false,
        'label_controls' => array('add' => 'Add Product', 'remove' => 'Remove Product'),
    )
)); 

我希望这个字段在开始时有一个空的实体集合,因为该集合基于其他字段值,因此我不会在声明时放置任何 query_builder 参数。

$form->add($builder->getFormFactory()->createNamed(
    'supplier_list',
    'entity',
    null,
    array(
        'mapped' => false,
        'label' => ' ',
        'class' => 'SuppliersBundle:Suppliers',
        'empty_value' => '',
        'auto_initialize' => false,
        'required' => false,
        'data' => $data->getSupplierProduct(),
        'query_builder' => function(\Ella\SuppliersBundle\Repository\SuppliersRepository $er) {
                        return $er->createQueryBuilder('q')->andWhere('q.is_delete = 0')->orderBy('q.name', 'asc');
        })  
    )
);

一旦 supplier_list 字段有值,AJAX查询就会检索关联的元素并填充 cert_folder_product_factory 字段的集合。

为了在提交时验证表单并按照建议,我声明 PRE_SUBMIT EventListener来填充字段集合并验证用户选择的值

$builder->addEventListener(FormEvents::PRE_SUBMIT, function (FormEvent $event) use ($builder, $container) {
        $data = $event->getData();
        $form = $event->getForm();

        if (!$data['supplier_list']) {
            return;
        }

        $supplierId = $data['supplier_list'];

        $form->add($builder->getFormFactory()->createNamed(
                'cert_folder_product_factory',
                new EntityMultipleType(),
                null,
                array(
                        'label' => '',
                        'mapped' => false,
                        'class' => 'ProductsBundle:ProductFactory',
                        'empty_value' => '',
                        'auto_initialize' => false,
                        'required' => false,
                        'label_controls' => array('add' => 'Add Product', 'remove' => 'Remove Product'),
                        'query_builder' => function(\Ella\ProductsBundle\Repository\ProductFactoryRepository $er) use ($supplierId) {
                            return $er->getProductBySupplier($supplierId);
                        },
                )
            )
        );
    });

一旦我有 supplier_list 字段和表单提交的值,一切正常。但是,正如Symfony文档针对 query_builder 所解释的那样,query_builder param的默认行为是加载所有实体,使加载时间非常长,无需任何操作。

我的解决方法是强制加载一个任意实体

'query_builder' => function (\Ella\ProductsBundle\Repository\ProductFactoryRepository $er) {
    return $er->createQueryBuilder('q')->setMaxResults(1);
}

但是这个解决方案完全错误,强制实体集合首先加载0实体的任何正确方法都是错误的?

非常感谢您的帮助。

1 个答案:

答案 0 :(得分:0)

仅供参考,简单的做法是将null作为$supplierId参数的值传递,不会检索任何结果(仅当您在setParameter()中传递值时才有效QueryBuilder的)。

我还添加了https://symfony.com/doc/2.7/form/dynamic_form_modification.html#form-events-user-data中描述的formModifier,以避免在不同的EventListener

中复制/粘贴相同的字段
$formModifier = function (FormInterface $form, $supplierId = null, $productFactories = null) {
            $form->add('cert_folder_product_factory', new EntityMultipleType(),
                    array(
                        'label' => '',
                        'mapped' => false,
                        'class' => 'ProductsBundle:ProductFactory',
                        'empty_value' => '',
                        'auto_initialize' => false,
                        'required' => false,
                        'label_controls' => array('add' => 'Add Product', 'remove' => 'Remove Product'),
                        'query_builder' => function(\Ella\ProductsBundle\Repository\ProductFactoryRepository $er) use ($supplierId) {
                                return $er->getProductBySupplier($supplierId);
                        },
                        'data' => (count($productFactories) > 0) ? $productFactories : null,
                    )
            );
        };

在PRE_SET_DATA中声明字段

$builder->addEventListener(FormEvents::PRE_SET_DATA, function (FormEvent $event) use ($formModifier, $builder, $container) {
     $formModifier($form,
            ($data->getSupplierProduct()) ? $data->getSupplierProduct()->getId() : null,
            (count($data->getProductFactory())) ? $data->getProductFactory() : null
    );
}

然后在PRE_SUBMIT中验证表单提交

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

        $formModifier($form,
                array_key_exists('supplier_list', $data) ? $data['supplier_list'] : null
        );
});