Как реализовать форму фильтра поиска с Symfony2

У меня есть список элементов для отображения на странице с формой поиска над ним для фильтрации этих элементов, как и в любом обычном бэкэнде. Проблема в том, что я не знаю, как добавить критерии поиска в существующий запрос с соединениями... Вот что у меня есть:

Я использую специальный метод в репозитории, связанном с сущностью, для добавления соединений в запрос (во избежание множества запросов). Контроллер выглядит так:

class ModelController extends Controller
{
    public function indexAction(Request $request)
    {
        // ...
        $em = $this->getDoctrine()->getManager();
        $query = $em->getRepository('AcmeDemoBundle:Item')->getList();
    }
}

Метод getList в репозитории выглядит так:

use Doctrine\ORM\EntityRepository;

// ...

class ItemRepository extends EntityRepository
{
    public function getList()
    {
        $queryBuilder = $this
            ->createQueryBuilder('i')
            ->innerJoin('i.brand', 'b');

        return $queryBuilder->getQuery();
    }
}

Я создал объект формы ItemSearchType с несколькими полями для поиска элементов.

Как я могу легко добавить критерии поиска из данных, представленных в форме поиска, для отображения отфильтрованных элементов?

Это то, что в моем контроллере относительно формы поиска:

class ModelController extends Controller
{
    public function indexAction(Request $request)
    {

        // ...
        if ($request->getMethod() === 'POST') {
           $searchForm->bindRequest($request);

           if ($searchForm->isValid()) {
               $searchCriteria = $searchForm->getData();

              // Do something with this data! ...but I don't know how
           }
     }
}

Спасибо!


person Michaël Perrin    schedule 12.07.2012    source источник


Ответы (2)


Вот что я бы попробовал:

public function getListBy($criteria)
{
    $qb = $this->createQueryBuilder('i');

    $qb->innerJoin('i.brand', 'b');

    foreach ($criteria as $field => $value) {
        if (!$this->getClassMetadata()->hasField($field)) {
            // Make sure we only use existing fields (avoid any injection)
            continue;
        }

        $qb ->andWhere($qb->expr()->eq('i.'.$field, ':i_'.$field))
            ->setParameter('i_'.$field, $value);
    }

    return $qb->getQuery()->getResult();
}
person AdrienBrault    schedule 12.07.2012

Здесь я разместил ответ для этого, я использую LexikFormFilterBundle filterTypes и QueryBuilder, а также созданный мной TypeGuesser, который абстрагирует процесс создания filterForm.

вы можете установить обе службы как отдельные пакеты с помощью Composer. Полученный код чище

Из README, если вы не хотите переходить на github: P

/**
 * Creates a Filter form to search for Entities.
 *
 * @param AbstractType|string $formType The `generate:doctrine:form` generated Type or its FQCN.
 *
 * @return \Symfony\Component\Form\Form The filter Form
 */
private function createFilterForm($formType)
{
    $adapter = $this->get('dd_form.form_adapter');
    $form = $adapter->adaptForm(
        $formType,
        $this->generateUrl('document_search'),
        array('fieldToRemove1', 'fieldToRemove2')
    );
    return $form;
}

Он не работает для SF >= 2.8 Требуется исправление здесь

person juanmf    schedule 10.04.2014
comment
Это лучший ответ. LexikFormFilterBundle решает проблему фильтрации сущности. Ответ AdrienBrault также будет работать, но он не может фильтровать, например, по диапазону дат. - person Stephan Vierkant; 04.03.2016
comment
Спасибо за совет с LexikFormFilterBundle, мне надоели все andWheres в запросах фильтра. комплект фильтров экономит много работы и усложняет там :) - person ; 27.04.2017