vidy videni
vidy videni

Reputation: 271

Symfony: how to add a sub set of items from big collection to entity type?

A car machine oil is applicable to several car models, but in my case, there are hundreds of car models in our system, I don't want to load them all to a page, then , let a user to choose specific car models, it would be better to use ajax call to get car model by car brand , car series. the user choose a sub collection of items , post these selected to server.

In the form type ,I add a form field like this below, as we know, if I don't set its option choices as empty array, the entity field will get all car models , which will result in huge performance penalty.

->add('applicableModels', 'entity', array(
                        'class' => 'VMSP\CarBundle\Entity\CarModel',
                        'choices'=>array(),
                        'multiple'=>true,
                        'property_path' => "modelName",
                        'label' => 'vmsp_product.product.form.applicable_model',
                    )
          )

So, how do you add a sub set of items from a big collection , and assign these selected items to entity type?

Upvotes: 0

Views: 1074

Answers (1)

Francesco Abeni
Francesco Abeni

Reputation: 4265

The simple answer is that you can define a custom query builder for each element, you add to the form, i.e.

$data = $builder->getData();
\\...
->add('applicableModels', 'entity', array(
    'class' => 'VMSP\CarBundle\Entity\CarModel',
    'multiple' => true,
    'property_path' => "modelName",
    'label' => 'vmsp_product.product.form.applicable_model',
    'query_builder' => function (EntityRepository $er) use ($data) {
        $qb = $er->createQueryBuilder('e')
                ->where('e.manufacturer IN (:manufacturer)')
                ->setParameter('manufacturer', $data['manufacturer']);
        return $qb->orderBy('e.name');
    },
))

So you may have a sort of a "wizard" where user select a manufacturer, the page reloads, and the cars shown are only a subset.

In a very similar situation I ended up doing things a little differently, though. In the form, the choices are set to an empty array. On frontend, the options are filled via Ajax calling a separate API. Then on the form "pre-submit" event, I fill the field with the selected option.

$builder->addEventListener(
        FormEvents::PRE_SUBMIT, function (FormEvent $event) {
        $form = $event->getForm();
        $data = $event->getData();
        if (!empty($data['applicable_model'])) {
            $form->add('applicable_model', 'entity', array(
                'class' => 'VMSP\CarBundle\Entity\CarModel',
                'query_builder' => function (EntityRepository $er) use ($data) {
                    $qb = $er->createQueryBuilder('e')
                        ->where('e.id IN (:applicable_model)')
                        ->setParameter('applicable_model', $data['applicable_model']);
                    return $qb;
                },
            ));
        }

Update: I learned that the addEventListener part can probably be replaced by a DataTransforme instead, see https://stackoverflow.com/a/31938905/410761

Upvotes: 2

Related Questions