Фильтрация с помощью symfony2 - PullRequest
       18

Фильтрация с помощью symfony2

5 голосов
/ 03 августа 2011

Существует ли какой-либо код с открытым исходным кодом (или пример) для Symfony2, который может фильтровать определенную модель, используя несколько параметров? Хороший пример того, что я ищу, можно увидеть на этой веб-странице Trulia.

http://www.trulia.com/for_sale/30000-1000000_price/10001_zip/

http://www.trulia.com/for_rent/Chicago,IL/#for_rent/Chicago,IL/0-500_price/wd,dw_amenities/sm_dogs_pets"

http://www.trulia.com/for_rent/Chicago,IL/#for_rent/Chicago,IL/400-500_price/wd,dw_amenities

http://www.trulia.com/for_rent/Chicago,IL/#for_rent/Chicago,IL/wd,dw_amenities"

http://www.trulia.com/for_rent/Chicago,IL/#for_rent/Chicago,IL/400p_price/dw,cs_amenities

http://www.trulia.com/for_rent/Chicago,IL/#for_rent/Chicago,IL/1p_beds/1p_baths/400p_price/dw,cs_amenities

Обратите внимание, как URL создается при нажатии в форме. Я полагаю, используется один контроллер для всех этих маршрутов. Как это делается? Я не думаю, что это будет перенаправление всех возможных маршрутов на конкретный контроллер (показано ниже), может быть, какая-то динамическая маршрутизация?

/**
 * @Route("/for_rent/{state}/{beds}_beds/{bath}_bath/{mix_price}-{max_price}_price /{amenities_list}
 * @Route("/for_rent/{state}/{mix_price}-{max_price}_price/{amenities_list}
 * @Route("/for_rent/{state}/{bath}_bath/{mix_price}-{max_price}_price/{amenities_list}
 * @Route("/for_rent/{state}/{mix_price}_price/{amenities_list}
 * @Route("/for_rent/{state}/{beds}_beds/{bath}_bath/{amenities_list}    
 * ........
 */

public function filterAction($state, $beds, $bath, $min_price, $max_price ....)
{
    ....
}

Спасибо.

Ответы [ 4 ]

1 голос
/ 07 августа 2011

Чтобы построить ваши маршруты, я уверен, что вы просмотрели страницу документации Routing , но заметили ли вы, что вы можете устанавливать требования к маршрутам? Эта страница объясняет, как это сделать с аннотациями.

Что касается фильтрации, я полагаю, что с DQL все будет в порядке, но вы также можете написать прямой SQL с помощью Doctrine и отобразить результаты вашего запроса в одну или несколько сущностей. Это описано здесь . Может быть более гибким, чем DQL.

1 голос
/ 03 августа 2011

Для простых запросов (т. Е. Когда вам не нужно иметь диапазон данных, например, минимальное-максимальное значение), вы можете использовать хранилище сущностей для поиска сущностей по заданным параметрам запроса.Предполагая, что ваша сущность имеет вид Acme\FooBundle\Entity\Bar:

$em = $this->getDoctrine()->getEntityManager();
$repo = $em->getRepository('AcmeFooBundle:Bar');

$criteria = array(
    'state' => $state,
    'beds' => $beds,
    // and so on...
);
$data = $repo->findBy($criteria);

При построении массива $criteria вам, вероятно, понадобится некоторая логика, чтобы вы сортировали только по предоставленным критериям, а не по всем возможным значениям.,$data будет содержать все объекты, которые соответствуют критериям.

Для более сложных запросов вы захотите изучить DQL (и, возможно, пользовательский репозиторий ) для более тонкого контроля над объектами, которые вы извлекаете.

0 голосов
/ 26 апреля 2014

Существует замечательный пакет под названием LexikFormFilterBundle "lexik/form-filter-bundle": "~2.0", который помогает генерировать сложный DQL после заполнения пользователем формы фильтра.

Я создал пакет, который зависит от него, который меняет типыданный FormType (например, сгенерированный SencioGeneratorBundle) Таким образом, вы можете отобразить правильную FilterForm и затем создать DQL после него (с Lexik).

Вы можете установить его с помощью Composer, следуя этому README.md

Все, что он делает, это переопределяет Guesser Type Doctrine, который предлагает требуемый FormType для каждого поля Entity, и заменяет данный Type на соответствующий LexikFormFilterType.Например, заменяет простой NumberType на filter_number, который отображает в виде двух чисел, границ Max и Min.

private function createFilterForm($formType)
{
    $adapter = $this->get('dd_form.form_adapter');
    $form = $adapter->adaptForm(
        $formType,
        $this->generateUrl('document_search'),
        array('fieldToRemove1', 'fieldToRemove2')
    );
    return $form;
}

После отправки формы вы просто передаете ее Lexik и запускаете сгенерированный запрос, как показано в моем примере.

public function searchAction(Request $request)
{
    // $docType = new FormType/FQCN() could do too.
    $docType = 'FormType/FQCN';
    $filterForm = $this->createFilterForm($docType);
    $filterForm->handleRequest($request);

    $filterBuilder = $this->getDocRepo($docType)
        ->createQueryBuilder('e');
    $this->get('lexik_form_filter.query_builder_updater')
        ->addFilterConditions($filterForm, $filterBuilder);

    $entities = $filterBuilder->getQuery()->execute();

    return array(
        'entities'   => $entities,
        'filterForm' => $filterForm->createView(),
    );
}
0 голосов
/ 15 августа 2013

csg, ваше решение хорошо (с @Route ("/ search / {q}), если вам нужно использовать маршрутизацию только в" одностороннем порядке ". Но что если вам нужно будет напечатать некоторые ссылки ценового фильтра на страницедоступно по URL: http://www.trulia.com/for_sale/30000-1000000_price/10001_zip/

В случае @Route("/search/{q} вы не сможете использовать метод маршрутизации, генерирующий URL с параметрами.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...