El tutorial Jobeet

7.6. Paginación

Uno de los requisitos establecidos durante el día dos decía que "el listado de ofertas de trabajo de la página de cada categoría incluye una paginación con 20 ofertas por página".

La paginación de los listados de objetos Propel se realiza mediante una clase específica llamada sfPropelPager. En la acción category, en vez de pasar a la plantilla showSuccess los objetos que representan las ofertas de trabajo, pasamos un objeto paginador:

// apps/frontend/modules/category/actions/actions.class.php
public function executeShow(sfWebRequest $request)
{
  $this->category = $this->getRoute()->getObject();

  $this->pager = new sfPropelPager(
    'JobeetJob',
    sfConfig::get('app_max_jobs_on_category')
  );
  $this->pager->setCriteria($this->category->getActiveJobsCriteria());
  $this->pager->setPage($request->getParameter('page', 1));
  $this->pager->init();
}

Nota El método sfRequest::getParameter() admite un segundo parámetro que indica el valor por defecto cuando el primer argumento no existe. En el código de la acción anterior, si el parámetro page de la petición no existe, el método getParameter() devuelve 1.

El constructor de sfPropelPager toma como argumentos la clase del modelo y el máximo número de elementos por página. Por tanto, es necesario que añadas este último valor al archivo de configuración:

# apps/frontend/config/app.yml
all:
  active_days:          30
  max_jobs_on_homepage: 10
  max_jobs_on_category: 20

Por su parte, el método sfPropelPager::setCriteria() toma como primer argumento el objeto Criteria que se debe utilizar para obtener los registros de la base de datos.

Añade el método getActiveJobsCriteria():

// lib/model/JobeetCategory.php
public function getActiveJobsCriteria()
{
  $criteria = new Criteria();
  $criteria->add(JobeetJobPeer::CATEGORY_ID, $this->getId());

  return JobeetJobPeer::addActiveJobsCriteria($criteria);
}

Ahora que hemos definido el método getActiveJobsCriteria(), podemos refactorizar los otros métodos de JobeetCategory para que lo utilicen:

// lib/model/JobeetCategory.php
public function getActiveJobs($max = 10)
{
  $criteria = $this->getActiveJobsCriteria();
  $criteria->setLimit($max);

  return JobeetJobPeer::doSelect($criteria);
}

public function countActiveJobs()
{
  $criteria = $this->getActiveJobsCriteria();

  return JobeetJobPeer::doCount($criteria);
}

Por último, actualiza la plantilla:

<!-- apps/frontend/modules/category/templates/showSuccess.php -->
<?php use_stylesheet('jobs.css') ?>

<?php slot('title', sprintf('Jobs in the %s category', $category->getName())) ?>

<div class="category">
  <div class="feed">
    <a href="">Feed</a>
  </div>
  <h1><?php echo $category ?></h1>
</div>

<?php include_partial('job/list', array('jobs' => $pager->getResults())) ?>

<?php if ($pager->haveToPaginate()): ?>
  <div class="pagination">
    <a href="<?php echo url_for('category', $category) ?>?page=1">
      <img src="/images/first.png" alt="First page" />
    </a>

    <a href="<?php echo url_for('category', $category) ?>?page=<?php echo $pager->getPreviousPage() ?>">
      <img src="/images/previous.png" alt="Previous page" title="Previous page" />
    </a>

    <?php foreach ($pager->getLinks() as $page): ?>
      <?php if ($page == $pager->getPage()): ?>
        <?php echo $page ?>
      <?php else: ?>
        <a href="<?php echo url_for('category', $category) ?>?page=<?php echo $page ?>"><?php echo $page ?></a>
      <?php endif; ?>
    <?php endforeach; ?>

    <a href="<?php echo url_for('category', $category) ?>?page=<?php echo $pager->getNextPage() ?>">
      <img src="/images/next.png" alt="Next page" title="Next page" />
    </a>

    <a href="<?php echo url_for('category', $category) ?>?page=<?php echo $pager->getLastPage() ?>">
      <img src="/images/last.png" alt="Last page" title="Last page" />
    </a>
  </div>
<?php endif; ?>

<div class="pagination_desc">
  <strong><?php echo $pager->getNbResults() ?></strong> jobs in this category

  <?php if ($pager->haveToPaginate()): ?>
    - page <strong><?php echo $pager->getPage() ?>/<?php echo $pager->getLastPage() ?></strong>
  <?php endif; ?>
</div>

La mayoría del código anterior se encarga de enlazar otras páginas del paginador. A continuación se muestran otros métodos de sfPropelPager que utiliza esta plantilla:

  • getResults(): devuelve un array con los objetos Propel de la página actual
  • getNbResults(): devuelve el número total de resultados
  • haveToPaginate(): devuelve true si existe más de una página
  • getLinks(): devuelve una lista de enlaces a todas las páginas del paginador
  • getPage(): devuelve el número de la página actual
  • getPreviousPage(): devuelve el número de la página anterior
  • getNextPage(): devuelve el número de la página siguiente
  • getLastPage(): devuelve el número de la última página
Paginación en el listado de ofertas de trabajo de una categoría

Figura 7.2 Paginación en el listado de ofertas de trabajo de una categoría