in Профессиональное

Symfony snippet: partial для постраничной навигации (pagination)

Предлагаю вашему вниманию небольшой сниппет для повседневного применения в symfony 1.3 – 1.4.

Сниппет предназначен для отображения постраничной навигации по записям.

Задача:

выводить список страниц для типового набора записей (новости, каталог и т.п.)

Решение:

Поскольку пейджер в большинстве типовых проектов требуется однотипный, то и решение для него должно быть простым и универсальным. Для бОльшей наглядости предположим что у нас есть модель NewsItem – новости сайта.

Подготовительные операции:

Схема:

NewsItem:
  options:
    type: INNODB
    collate: utf8_general_ci
    charset: utf8
  actAs:
    Timestampable:
  connection: doctrine
  tableName: news_item
  columns:
    id:
      type: integer(4)
      fixed: false
      unsigned: false
      primary: true
      autoincrement: true
    title:
      type: string(255)
      fixed: false
      unsigned: false
      primary: false
      notnull: true
      autoincrement: false
    abstract:
      type: string()
      fixed: false
      unsigned: false
      primary: false
      notnull: true
      autoincrement: false
    description:
      type: string()
      fixed: false
      unsigned: false
      primary: false
      notnull: true
      autoincrement: false
    is_published:
      type: boolean
      fixed: false
      unsigned: false
      primary: false
      default: '0'
      notnull: true
      autoincrement: false

Метод получения пейджера в NewsItemTable.class.php:

// Где-то в lib/model/doctrine/NewsItemTable.class.php
/**
 * Что-то с постраничным выводом
 * @param <int> $page
 * @return <Doctrine_Pager>
 */
public static function getNewsPager( $page )
{
  $query = Doctrine_Query::create()
    ->select    ( "*" )
    ->from      ( "NewsItem n" )
    ->where     ( "n.is_published = 1" )
    ->orderBy   ( "n.created_at DESC" );
  return new Doctrine_Pager( $query, $page, sfConfig::get( "app_pager_perpage", 10 ));
}

Настройку app_pager_perpage добавляем в app.yml:

# apps/frontend/config/app.yml
all:
  pager:
    perpage: 10

В действии:

// apps/frontend/modules/news/actions/actions.class.php
/**
 * Архив новостей
 * @param  $request
 */
public function executeArchive(sfWebRequest $request)
{
  $this->news_pager = NewsItemTable::getNewsPager( $request->getParameter( "page", 1 ) );
  $this->news       = $this->news_pager->execute();
}

Теперь создаем партиал пейджера (в каком-нибудь общем модуле, shared или commons):

// apps/frontend/modules/commons/templates/_pager.php
<?php
 
/**
 * Типовой пейджер
 *
 * @param <Doctrine_Pager> $pager - объект пейджера
 * @param <string> $route - маршрут для построения ссылок пейджера
 *
 * @package     commons
 * @subpackage  templates
 * @author      Dmitry.Bykadorov@gmail.com
 * @version     SVN: $Id: _pager.php dmitry.bykadorov $
 *
 */
 
?>
 
<?php if( $pager->haveToPaginate() ): ?>
<div class="pager">
 
  <ul>
    <?php if( $pager->getFirstPage() != $pager->getPage()): ?>
    <li><a href="<?php echo url_for( "$route?page=" . $pager->getFirstPage() ) ?>" title="<?php echo 'Первая страница'?>"><<</a></li>
    <li><a href="<?php echo url_for( "$route?page=" . $pager->getPreviousPage() ) ?>" title="<?php echo 'Назад'?>"><</a></li>
    <?php endif; ?>
 
    <?php for( $i = -2; $i < 3; $i++ ): ?>
      <?php if( ( $p = $pager->getPage() + $i ) > 0 && ( $p <= $pager->getLastPage() ) ): ?>
        <?php $active = ( $i == 0 ) ? "active" : ""; ?>
        <li><a class="<?php echo $active ?>" href="<?php echo url_for( "$route?page=" . $p ) ?>" title="<?php echo 'Страница ' . $p ?>"><?php echo $p ?></a></li>
      <?php endif; ?>
    <?php endfor; ?>
 
    <?php if( $pager->getLastPage() != $pager->getPage()): ?>
    <li><a href="<?php echo url_for( "$route?page=" . $pager->getNextPage() ) ?>" title="<?php echo 'Вперед'?>">></a></li>
    <li><a href="<?php echo url_for( "$route?page=" . $pager->getLastPage() ) ?>" title="<?php echo 'Последняя страница'?>">>></a></li>
    <?php endif; ?>
  </ul>
 
</div>
<?php endif; ?>

Ну и все что нам осталось, разместить в шаблоне архива постраничную навигацию:

// apps/frontend/modules/news/templates/archiveSuccess.php
<?php
include_partial(
  "commons/pager",
  array(
    "pager" => $news_pager,
    "route" => "@news_archive"
));
?>

Вот и все. Можно пользоваться.

Пожелания, предложения и багрепорты оставляйте в комментариях )

Write a Comment

Comment

ERROR: si-captcha.php plugin: GD image support not detected in PHP!

Contact your web host and ask them to enable GD image support for PHP.

ERROR: si-captcha.php plugin: imagepng function not detected in PHP!

Contact your web host and ask them to enable imagepng for PHP.

13 Comments

  1. На самом деле я тут ни при чём, этот сниппет был опубликован вроде как Nicolas Perriault у него в блоге.


  2. <a href="getNextPage() ) ?>" title="">>

    о господи, какой ужас, разве же так можно?

    должно быть так

    getNextPage()) ?>

  3. Помогите пожалуйста с этой постраничной навигацией

    уже голова трищит

  4. как делать инклюдом на страницу
    обшем у миня сраница на которую инклюдом подвязываю контент и тепер появилось уже 4 статьи и хочу на ту же страницу зделать постраничной навигацией не делая других помогите решить пожалуйста

    • Ну так если symfony – берите этот сниппет и делайте ) Или переформулируйте вопрос.

  5. сраница на которую инклюдом подвязываю контент и тепер появилось уже 4 статьи для этой станицы и хочу на ту же страницу зделать постраничной навигацией инклюдом как 1.2.3.4. по одной

    • Если вы считаете что я напишу код за вас, то это не так ) Но могу помочь наводящими вопросами. Пишите в скайп. Тут не чат все-таки.

  6. Спасибо за пост. Разобрался с pager, а то их jobeet что то тяжелее в понимании 🙂

  7. Подскажите пожалуйста как использовать методы с sfPager, а то я что то никак не пойму
    http://www.symfony-project.org/api/1_4/sfPager

    Или же как вывести общее количество страниц, или найденных объектов. Пример что в jobeet почему то не работает.