Lucene Search and Symfony Pagination

In our efforts to abstract our list results to a state that it can be re-used for other purposes, some work has been done to return search results to a results page

The Results partial

The results partial itself is called, when the executeSearch action is called in

apps/frontend/modules/staff/actions/actions.class.php:

public function executeSearch(sfWebRequest $request)
{
  $this->forwardUnless($query = $request->getParameter('query'), 'staff', 'index');
  $lqResults = Doctrine_core::getTable('agPerson')->getForLuceneQuery($query);
  $this->pager = new sfDoctrinePager('agPerson', 5);
  $i = 0;
  $lqIds = array();
  foreach($lqResults as $lqResult)
  {
    $lqIds[$i] = $lqResult->getId();
    $i++;
  }
  if (count($lqIds) > 0) 
  {
    $q = Doctrine::getTable('agPerson')
      ->createQuery('a')
      ->select('p.*')
      ->from('agPerson p')
      ->where('p.id IN ('.implode(',',$lqIds).')');
    $this->pager->setQuery($q);
    $this->pager->setPage($request->getParameter('page', 1));
    $this->pager->init();
  }
  $this->query = $query;
}
</code?

What the above does is passes the search results to our pager.
But that's not all.

The ''$query'' variable is the search string submitted by the user from the frontend. It is used to perform the Lucene search, and the resulting @Doctrine_Collection@ (of @agPerson@ objects) is held in ''$lqResults''. The ID of each ''agPerson'' in ''lqResults'' is then passed into the ''$lqIds'' array so it can be used to create the query for the pager.

After that, a check is done to see if Lucene has returned any values, and then the query is created. The query selects objects from the @agPerson@ table with IDs matching the values in ''$lqIds''. The final step is to set the query of ''staffActions/search'' to ''$query'' so it can be accessed by ''searchSuccess.php'' when it is called. 

<code>
<div id="persons">
  <?php include_partial('staff/results', array('pager' => $pager, 'query' => $query)) ?>
</div>

apps/frontend/modules/staff/templates/_results.php

This file currently works just like any other indexSuccess or listing page, but it receives a pager instead of a whole table. It also doesn't include much code of its own, instead it includes the partial _results.php. This allows _results.php to be reused in other places and prevents code duplification.

The code in searchSuccess is important though. The single line of PHP tells Symfony which module and partial to use, and also passes the $pager and $query objects into _results.php.

_results.php is the final step in the process, and this file is very similar to the staff module's indexSuccess.php. The only significant difference is in the creation of the links to the pager's various pages.

//This block creates the navigation links for paginated staff members.
//
//First Page link (or inactive if we're at the first page).
    if(!$pager->isFirstPage())
    {
      echo '<a href="' . url_for('staff/search') . '/page/' . $pager->getFirstPage() . '?query=' . $query . '" class="buttonText" title="First Page">&lt;&lt;</a>';
    }
    else
    {
      echo '<a class="buttonTextOff">&lt;&lt;</a>';
    }

//Previous Page link (or inactive if we're at the first page).
    if(!$pager->isFirstPage())
    {
      echo '<a href="' . url_for('staff/search') . '/page/' . $pager->getPreviousPage() . '?query=' . $query . '" class="buttonText" title="Previous Page">&lt;</a>';
    }
    else
    {
      echo '<a class="buttonTextOff">&lt;</a>';
    }

//Next Page link (or inactive if we're at the last page).
    if(!$pager->isLastPage())
    {
      echo '<a href="' . url_for('staff/search') . '/page/' . $pager->getNextPage() . '?query=' . $query . '" class="buttonText" title="Next Page">&gt;</a>';
    }
    else
    {
      echo '<a class="buttonTextOff">&gt;</a>';
    }

//Last Page link (or inactive if we're at the last page).
    if(!$pager->isLastPage())
    {
      echo '<a href="' . url_for('staff/search') . '/page/' . $pager->getLastPage() . '?query=' . $query . '" class="buttonText" title="Last Page">&gt;&gt;</a>';
    }
    else
    {
      echo '<a class="buttonTextOff">&gt;&gt;</a>';
    }

The if statements check to see which page you are on to determine if page navigation <a> tags should be active or not by setting the class on the elements.

The links are constructed by the @echo@ statements and are built from the path to the module and action, a static /page/ string, the relevant page to be linked to, a static ?query= string, and then the contents of query (which has been passed down from the action). In this way, pagination and search results are combined so only the results from agPerson are paginated rather than the contents of the entire table.


QR Code
QR Code agasti:developer:lucene_search_and_symfony_pagination (generated for current page)