Symfony2表单类型实体没有预加载

时间:2015-05-18 16:21:43

标签: php mysql symfony doctrine-orm

我正在建立一个带有>的网上商店40k产品。这些产品存储在MySQL表中(表格生成Symfony 2控制台和Doctrine 2)。

我有一个采购订单系统并创建了一个表单。

[table purchase_orders]

[table purchase_order_rows](fk purchase_order_id和fk product_id)

[表产品](产品(许多属性的RAM模块)(fk brand_id)

[table product_brands]

PurchaseOrderType.php

public function buildForm(FormBuilderInterface $builder, array $options)
{
    $builder
        ->add('customer', 'entity', array(
            'class' => 'MyShop\Bundle\CustomerBundle\Entity\Customer',
            'multiple' => false
        ))
        ->add('purchaseOrderStatus', 'entity', array(
            'class' => 'AppBundle\Entity\PurchaseOrderStatus',
            'multiple' => false
        ))
        ->add('date')
        ->add('reference')
        ->add('comments')
        ->add('purchaseOrderRows', 'collection', [
            'type' => new PurchaseOrderRowType(),
            'allow_add' => true,
            'by_reference' => false,
        ])
    ;
}

PurchaseOrderRowType

public function buildForm(FormBuilderInterface $builder, array $options)
{
    $builder
        ->add('purchaseOrder', 'entity', array(
            'class' => 'AppBundle\Bundle\OrderBundle\Entity\PurchaseOrder',
            'multiple' => false
        ))
        ->add('ram', 'entity', array(
            'class' => 'MyShop\Bundle\ProductBundle\Entity\Ram',
            'multiple' => false,
        ))
        ->add('purchaseOrderRowStatus', 'entity', array(
            'class' => 'AppBundle\Entity\PurchaseOrderRowStatus',
            'multiple' => false
        ))
        ->add('description')
        ->add('count')
        ->add('startDate')
        ->add('endDate')
        ->add('amount')
        ->add('taxAmount')
        ->add('discountAmount')
    ;
}

当我使用Doctrine生成表单时,它会从products表中加载所有行,这会导致非常慢/不可加载的网页。 如何设法不预先加载所有这些产品?每个产品都有一个唯一的条形码,用户和数据库都知道。用户只需输入条形码,而不是从下拉列表中选择产品。

我一直在尝试将关键query_builder添加到 - > add('ram','entity'但这不会导致解决方案,我卡住了......

同时添加新的采购订单的成本超过30秒!我怀疑这个问题也会引起这种情况。

非常感谢任何帮助。

2 个答案:

答案 0 :(得分:1)

我能看到的一个解决方案是创建一个DataTransformer,它将条形码转换为产品实体和v.v. Here是几乎准备好的示例,您可以稍微更改并使用它,可选地,您可以向该文本字段添加一些jquery插件(例如自动完成)以获得更多可用性。

答案 1 :(得分:1)

我们遇到了类似的问题,这是我们提出的解决方案:

您应该考虑创建最终类 ProductForChoice,将EntityManager作为依赖项和单个调用方法:

/**
* Class ProductForChoice
*/
final class ProductForChoice 
{

    /** @var EntityManager */
    protected $entityManager;

    function __construct(EntityManager $entityManager)
    {
        $this->entityManager = $entityManager;
    }

    public function invoke()
    {
        $dql = "
            SELECT product.id, product.barCode as bar_code
            FROM Entity/Product as product

        ";
        $query = $this->entityManager->createQuery($dql);

        $results =  $query->useResultCache(true, 300)->getArrayResult();

        $ret = [];

        foreach ($results as $result) {
            $ret[$result['id']] = $result['bar_code'];
        }

        return $ret;

    }

}

然后在确定将此类注册为服务之后,您可以以这种方式在抽象类型中使用它:

 ->add('product', 'filter_choice', [
            'required' => false,
            'choices' => $this->ProductForChoiceAsService->invoke(),
            'label' => 'Products',
        ]);

请注意,在此示例中,存在 filter_choice ,而不是实体

作为旁注,如果你想保留你的抽象类型,dependecy-clean你可能想要传递 ProductForChoiceAsService  在表单选项中,而不是使用__constructor,您的电话。

为了帮助用户完成任务,可以考虑采用 Choosen,这是一个非常讨厌的工具,可以将多选项转换为类似搜索的输入框。

希望它有所帮助, 问候。