Могу ли я использовать запрос в построителе форм, чтобы получить фильтрованную коллекцию в форме symfony

В AcmePizza BUndle это работает нормально

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

Могу ли я сделать что-то подобное в коллекции

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

Solutions Collecting From Web of "Могу ли я использовать запрос в построителе форм, чтобы получить фильтрованную коллекцию в форме symfony"

Предполагая, что ваши пользовательские задачи – это отношения. Здесь вы найдете ответ для своего дела. Это только то, как сортировать, но если вам потребовались некоторые условия WHERE, это не так просто, но это не сложно.

Мне пришлось отфильтровывать некоторые объекты, ключом к его решению было создание метода set / get в классе сущности, возвращающем требуемый набор.

В моем случае это выглядит так

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

И при создании формы имя для поля является «customvalues» вместо «values». Поэтому моя коллекция содержит только значения с настраиваемым полем true.

Я указываю вам в правильном направлении (надеюсь):

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

В этой статье рассматриваются зависимости полей. например, когда вы выбираете страну, у вас есть города, принадлежащие стране, которая появляется в списке.

Вы часто хотите фильтровать коллекцию, когда вы обновляете объект, а не новый, не так ли?

Вот рабочее решение, это пример из контроллера (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 ())

Ключевым моментом здесь является использование критериев Доктрины, подробнее здесь:

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

Также подумайте о том, чтобы переместить критерии в сущности, сделать там общественный метод. Когда вы загружаете его из базы данных, вы можете запустить этот метод, используя обратный вызов жизненного цикла postLoad доктрины. Конечно, положить его в сущность будет работать, если вы не нуждаетесь в каких-либо услугах или подобных вещах.

Возможно, еще одно решение – переместить критерии в событие формы внутри класса Form, если вам нужна фильтрация только внутри формы.

Если вам необходимо, чтобы фильтрация коллекции была прозрачно реализована во всем проекте, напишите слушателя доктрины и поместите код внутри метода postLoad (). Вы также можете вводить зависимости в приемнике доктрины, но я рекомендую сам контейнер для инъекций из-за ленивой загрузки других сервисов, поэтому вы не получаете ссылки на циркулярную службу.

Удачи!

В Symfony 2.7 я решил это, выполнив следующее в 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', )); } } 

Да.

В вашем классе UserTaskType добавьте следующий метод.

 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'); } ); }