I'm creating a form that modifies the query of KnpPaginatorBundle in order to show filtered paginated results.
To do that. When the form is valid I build the querystring (concatenating) with the required fields to filter. I set $filteredDql variable with my custom query. The problem is that it's value only remains for the first page. When I change the page it turns to NULL. And pagination resets...
I think, the problem could be that I'm setting the $filteredDql variable in a block context (when the form is valid only).
How I can set $filteredDql variable for the whole operation or application wide ? maybe using parameters ? I tried using the container from the controller without success using:
$this->container->setParameter('key', value);
$this->container->getParameter('key');
$this->container->HasParameter('key');
But this way I'm getting 500 Internal Server Error
Here's the code:
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
)
);
}
Finally solved it using a session variable to store the current filters. Sessions are application wide or stateless. I'm quite happy with this approach :D
Although, It's a shame that KnpPaginatorBundle can't remember custom query "filters" (WHERE, GROUP BY, ...) through pagination by default when data comes from form validation :S And just support it by using the sortable functions to make links to sort asc or desc its a shame...
Here's the code:
/**
* @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
)
);
}