简体   繁体   中英

Symfony2 form types entity no pre load

I'm building a webshop with > 40k products. Those products are stored in a MySQL table (table is generated which Symfony 2 console and Doctrine 2).

I have an purchase order system and created a form.

[table purchase_orders]

[table purchase_order_rows] (fk purchase_order_id and fk product_id)

[table products] (products (RAM modules which a lot of properties) (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')
    ;
}

When I'm generating the form with Doctrine it loads ALL the rows from the products table which leads to a very slow / non loadable web page. How can I manage to not pre load all those products? Each product has a unique bar code which is known by the user and the database. The user just needs to enter the bar code instead of selecting the product from a dropdown list.

I have been experimenting with adding the key query_builder to the ->add('ram', 'entity' but this did not lead to a solution, I got stuck...

Also adding a new purchase order costs more than 30 seconds! I suspect this issue causes that as well.

Any help would be kindly appreciated.

我可以看到的一个解决方案是创建一个DataTransformer ,它将条形码转换为产品实体和vv。 是几乎准备就绪的示例,您可以对其进行一些更改并使用它,还可以选择向该文本字段添加一些jquery插件(例如autocomplete),以获取更多信息可用性。

We had a similar issue and this is the solution we came up with:

You should consider creating a final class ProductForChoice, with the EntityManager as a dependency and a single invoke method:

/**
* 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;

    }

}

then after you made sure tho register this class as as service you can make use of it inside you abstract type in this fashion:

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

make note that, in this example a filter_choice is present and not an entity .

As a side note, if you want to keep your abstract type, dependecy-clean you may want to pass the ProductForChoiceAsService inside the form options instead of using the __constructor, your call.


To even more help the user in his quest consider adopting Choosen , it's a very hany tool to turn multi-select into search-like inputbox.

Hope it helps, Regards.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM