Подтвердить что ты не робот

Могу ли я использовать запрос в построителе форм, чтобы получить фильтрованную коллекцию в форме 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'); },
                ))
4b9b3361

Ответ 1

Предполагая, что ваши пользовательские задачи - это отношения, вы найдете ответ для своего случая здесь. Это как разбор, но если вам потребовались некоторые условия 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.

Ответ 2

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

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

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

Ответ 3

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

Вот рабочее решение, это пример из контроллера (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(). Вы также можете вводить зависимости в приемнике доктрины, но я рекомендую сам контейнер для инъекций из-за ленивой загрузки других сервисов, поэтому вы не получаете ссылки на круговые службы.

Удачи!

Ответ 4

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

}

Ответ 5

Да.

В вашем классе 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');
        }
    );
}