2013-02-11 5 views
0

Я создаю форму, которая изменяет запрос KnpPaginatorBundle, чтобы отображать отфильтрованные разбитые на страницы результаты.Запрос Symfony KnpPaginator с пользовательскими фильтрами из полей формы?

Для этого. Когда форма верна, я создаю цепочку (конкатенирование) с обязательными полями для фильтрации. Я задал переменную $ filterDql своим пользовательским запросом. Проблема в том, что это значение остается только для первой страницы. Когда я меняю страницу, она превращается в NULL. И разбиение на страницы сбрасывается ...

Я думаю, проблема может заключаться в том, что я устанавливаю переменную $ filterDql в контексте блока (когда форма действительна только).

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

$this->container->setParameter('key', value); 
$this->container->getParameter('key'); 
$this->container->HasParameter('key'); 

Но этот путь я получаю 500 Внутренняя ошибка сервера

Вот код:

public function indexAction(Request $request, $page) 
{ 
    $filters = new Filters(); 

    $form = $this->createForm(new FiltersType(), $filters); 

    $dql = "SELECT a FROM ViciousAmateurBundle:Post a WHERE a.is_active = true"; 

    if ($request->isMethod('POST')) { 
     $form->bind($request); 

     if ($form->isValid()) { 
      $country = $filters->getCountry(); 
      $city = $filters->getCity(); 
      $gender = $filters->getGender(); 
      $sexualOrientation = $filters->getSexualOrientation(); 

      if (isset($country)) { 
       $dql .= " AND a.country = '" . $filters->getCountry() . "'"; 
      } 
      if (isset($city)) { 
       $dql .= " AND a.city = '" . $filters->getCity() . "'"; 
      } 
      if (isset($gender)) { 
       $dql .= " AND a.gender = '" . $filters->getGender() . "'"; 
      } 
      if (isset($sexualOrientation)) { 
       $dql .= " AND a.sexual_orientation = '" . $filters->getSexualOrientation() . "'"; 
      } 
      $filteredDql = $dql; 
     } 
    } 

    $em = $this->get('doctrine.orm.entity_manager'); 

    if (isset($filteredDql)) { 
     $query = $em->createQuery($filteredDql); 
    } else { 
     $query = $em->createQuery($dql); 
    } 

    $paginator = $this->get('knp_paginator'); 
    $pagination = $paginator->paginate(
     $query, 
     $this->get('request')->query->get('page', $page), 
     5 
    ); 

    return $this->render('ViciousAmateurBundle:Default:index.html.twig', array(
     'form' => $form->createView(), 
     'pagination' => $pagination 
     ) 
    ); 
} 
+0

Посмотрите файл журнала, какие именно ошибки Вы получаете? –

+0

Когда я использую методы ** $ this-> container -> *** И получаю 500 Internal Server Error. Не записывает ничего нового. Использование dev или prod env. : S Когда вы не пытаетесь использовать параметры, приложение работает нормально. Но я не могу получить такое поведение, которое я хочу. – Jeflopo

ответ

0

Наконец решил его используя переменную сеанса для хранения текущих фильтров. Сеансы являются широкими или неактивными. Я вполне доволен этим подходом: D

Хотя, стыдно, что KnpPaginatorBundle не помнит пользовательские «фильтры фильтров» (WHERE, GROUP BY, ...) через разбиение по страницам по умолчанию, когда данные поступают из проверки формы : S И просто поддерживать его с помощью сортируемых функции, чтобы сделать ссылки сортировать по убыванию возрастанию или его позор ...

Вот код:

/** 
* @Route("/{page}", defaults={"page" = 1}, name="homepage") 
* @Route("/") 
* @Template() 
*/ 
public function indexAction(Request $request, $page) 
{ 
    $filters = new Filters(); 

    $form = $this->createForm(new FiltersType(), $filters); 

    $session = $this->getRequest()->getSession(); 

    if ($session->get('dql') == null) { 
     $session->set('dql', "SELECT a FROM ViciousAmateurBundle:Post a WHERE a.is_active = true"); 
    } 

    if ($request->isMethod('POST')) { 
     $form->bind($request); 

     if ($form->isValid()) { 
      $dql = "SELECT a FROM ViciousAmateurBundle:Post a WHERE a.is_active = true"; 
      $country = $filters->getCountry(); 
      $city = $filters->getCity(); 
      $gender = $filters->getGender(); 
      $sexualOrientation = $filters->getSexualOrientation(); 

      if (isset($country)) { 
       $dql .= " AND a.country = '" . $filters->getCountry() . "'"; 
      } 
      if (isset($city)) { 
       $dql .= " AND a.city = '" . $filters->getCity() . "'"; 
      } 
      if (isset($gender)) { 
       $dql .= " AND a.gender = '" . $filters->getGender() . "'"; 
      } 
      if (isset($sexualOrientation)) { 
       $dql .= " AND a.sexual_orientation = '" . $filters->getSexualOrientation() . "'"; 
      } 

      $session->set('dql', $dql); 
     } 
    } 

    $em = $this->get('doctrine.orm.entity_manager'); 

    $query = $em->createQuery($session->get('dql')); 

    $paginator = $this->get('knp_paginator'); 
    $pagination = $paginator->paginate(
     $query, 
     $this->get('request')->query->get('page', $page), 
     5 
    ); 

    return $this->render('ViciousAmateurBundle:Default:index.html.twig', array(
     'form' => $form->createView(), 
     'pagination' => $pagination 
     ) 
    ); 
} 
+0

Do * not * используйте этот код дословно. Предоставленный код небезопасен - имеет уязвимость в sql-инъекции. Чтобы избежать этого, используйте дескрипторы аргументов (именованные параметры) вместо ручной конкатенации значений с помощью DQL. Также построитель запросов doctrine имеет лучший API для построения запроса. Также я не вижу причин держать сгенерированный DQL в сеансе – jacekll