Can i use query in form builder to get filtered co

2019-03-15 06:05发布

IN the AcmePizza BUndle this is working fine

->add('pizza', 'entity', array(
                'class'         => 'Acme\PizzaBundle\Entity\Pizza',
                'query_builder' => function ($repository) { return $repository->createQueryBuilder('p')->orderBy('p.name', 'ASC'); },
            ))

Can i do something like that in collection

->add('userTasks','collection',array('type' => new UserTaskType(),
                    'class'         => 'acme\myBundle\Entity\UserTask',
                    'query_builder' => function ($repository) { return $repository->createQueryBuilder('p')->orderBy('p.name', 'ASC'); },
                ))

5条回答
手持菜刀,她持情操
2楼-- · 2019-03-15 06:19

Yes.

In your UserTaskType class, add the following method.

public function getDefaultOptions(array $options)
{
    return array(
        'data_class' => 'acme\myBundle\Entity\UserTask',
        'query_builder' => function($repo) {
            return $repo->createQueryBuilder('p')->orderBy('p.name', 'ASC');
        }
    );
}
查看更多
可以哭但决不认输i
3楼-- · 2019-03-15 06:23

Assuming Your userTasks is an relationship You will find answer for Your case here. These is just how to sort but if You had required some WHERE conditions it is not so simple but neither it is hard.

I had to filter out some entities, the key to solve it was to create set/get method in entity class returning required set.

In my case it looks like this

/**
 * Set values
 *
 * @param ArrayCollection $values
 * @return Attribute
 */
public function setCustomValues($values)
{
    $result = $this->getNotCustomValues();
    foreach ($values as $value)
    {
        $value->setAttribute($this);
        $result->add($value);
    }
    $this->values = $result;

    return $this;
}

/**
 * Get values
 *
 * @return \Doctrine\Common\Collections\Collection
 */
public function getCustomValues()
{
    $result = new ArrayCollection();
    foreach ($this->values as $value) {
        if($value->getCustom()) {
            $result->add($value);
        }
    }
    return $result;
}

And when creating form, name for a field is "customvalues" instead of "values" So my collection contains only values with custom field true.

查看更多
4楼-- · 2019-03-15 06:32

I point you to right direction (I hope) :

http://www.craftitonline.com/2011/08/symfony2-ajax-form-republish/

This article deals with field dependencies. for example, when you select a country, you have the towns that belongs to the country that appears in the list.

查看更多
冷血范
5楼-- · 2019-03-15 06:42

You often want to filter collection when you are updating an entity, not having a new one, right?

Here is a working solution, this is an example from controller (CRUD):

public function updateAction($id)
{
    $service = $this->getServiceRepository()->loadOne('id', $id);
    $this->checkPermission($service);

    $this->filterInventoryByPrimaryLocation($service);

    if($this->getFormHandler()->process('service_repair_service', $service, array('type' => 'update')))
    {
        $this->getEntityManager()->process('persist', $service);

        return $this->render('ServiceRepairBundle:Service:form_message.html.twig', [
            'message' => $this->trans('Service has been updated successfully.')
        ]);
    }

    return $this->render('ServiceRepairBundle:Service:form.html.twig', [
        'form' => $this->getFormHandler()->getForm()->createView(),
    ]);
}

private function filterInventoryByPrimaryLocation(Service $service)
{
    $inventory = $service->getInventory();

    $criteria = Criteria::create()
        ->where(Criteria::expr()->eq('location', $this->getUser()->getPrimaryLocation()))
        ->orderBy(array('timeInsert' => Criteria::ASC));

    $service->setInventory($inventory->matching($criteria));
}

$service = ENTITY, $inventory = ArrayCollection ( $service->getInventory() )

The key here is to use Doctrine's Criteria, more info here:

http://doctrine-orm.readthedocs.org/en/latest/reference/working-with-associations.html#filtering-collections

Also think of moving the Criteria in entity itself, make a public method there. When you load it from database, you can fire that method using doctrine's postLoad lifecycle callback. Ofcourse putting it in entity will work, if you don't require any services or things like that.

Another solution would probably be, to move the Criteria in a Form Event inside Form class, if you need filtering only inside a form.

If you need the collection filtering to be done transparently across whole project, write a doctrine listener and put the code inside a postLoad() method. You can also inject dependencies in doctrine listener, but I recommend injecting container itself, because of lazy loading other services, so you do not get circular service references.

Good luck!

查看更多
甜甜的少女心
6楼-- · 2019-03-15 06:45

In Symfony 2.7 i solved this by doing the following in the UserTaskType:

<?php

namespace AppBundle\Form;

use Symfony\Component\Form\AbstractType;
use Symfony\Component\Form\FormBuilderInterface;
use Symfony\Component\OptionsResolver\OptionsResolver;
use Doctrine\ORM\EntityRepository;

class UserTaskType extends AbstractType
{

    /**
     * @param FormBuilderInterface $builder
     * @param array $options
     */
    public function buildForm(FormBuilderInterface $builder, array $options)
    {

        $builder
            ->add('the_name', 'entity', array(
                'class' => 'acme\myBundle\Entity\UserTask',
                'query_builder' => function (EntityRepository $er) {
                    return $er->createQueryBuilder('u')
                        ->where('u.id > :id')
                        ->setParameter('id', '1')
                        ->orderBy('u.username', 'ASC');
                },
            ));
    }

    /**
     * @param OptionsResolver $resolver
     */
    public function configureOptions(OptionsResolver $resolver)
    {
        $resolver->setDefaults(array(
            'data_class' => 'acme\myBundle\Entity\UserTask',
        ));
    }

}
查看更多
登录 后发表回答