TRAJOIN is an Application to Translate symfony documents Jointly.

home > 1.2/cookbook/en > pager.txt

Edit this page

Show Markdown text

リストをパジネートする方法


概要


symfonyはページャコンポーネントを提供します: sfPropelPagerです。(Criteriaクラスの)クリテリアオブジェクトからの結果のリストを表示のためのページのセットに分割し、ページへのアクセスメソッドと結果オブジェクトを提供することが出来ます。


sfPropelPagerオブジェクト


sfPropelPagerクラスはモデルの章で説明されているPropel抽象化レイヤーを使用します。


この章ではシンプルな例でsfPropelPagerメソッドを使用する方法を説明します: 10×10の記事リストを表示することです。ArticleオブジェクトはgetPublished()getTitle()getOverview()getContent()アクセサメソッドを持ちます。


クリテリアリクエストのパジネートされていない結果が欲しい場合、次の内容が必要になります:



class articleActions extends sfActions
{
  public function executeList()
  {
    ...
    $c = new Criteria();
    $c->add(ArticlePeer::PUBLISHED, true);
    $articles = ArticlePeer::doSelect($c);
    $this->articles = $articles;
    ...
  }
}

$articles変数は、テンプレートからアクセス可能で、リクエストにマッチするArticleオブジェクトの配列を含みます。


パジネートされたリストを取得するために、微妙に異なるアプローチが必要です; 配列の代わりにsfPropelPagerオブジェクトに結果が収納されなければなりません:



class articleActions extends sfActions
{
  public function executeList()
  {
    ...
    $c = new Criteria();
    $c->add(ArticlePeer::PUBLISHED, true);
    $pager = new sfPropelPager('Article', 10);
    $pager->setCriteria($c);
    $pager->setPage($this->getRequestParameter('page', 1));
    $pager->init();
    $this->pager = $pager;
    ...
  }
}

このアクション以降で、クリテリアの定義の後で違いが始まります:


  • 10×10のArticleオブジェクトをパジネートするために新しいページャを作成します
  • クリテリアからページャへ影響を与える
  • 現在のページをリクエストされたページもしくは最初のものに設定する
  • ページャを初期化する(すなわち、クリテリアに関連したリクエストを実行する)
  • $pager変数経由でページャをテンプレートに渡す

listSuccess.phpテンプレートはsfPropelPagerオブジェクトをアクセスすることが出来ます。このオブジェクトは現在のページとすべてのページのリストを知っています。ページとページにあるオブジェクトをアクセスするメソッドを持ちます。操作する方法を見てみましょう。


結果のトータルの数字を表示するために、getNbResults()メソッドを使用して下さい:



<?php echo $pager->getNbResults() ?> results found.<br />
Displaying results <?php echo $pager->getFirstIndice() ?> to  <?php echo $pager->getLastIndice() ?>.

リクエストされたページの記事を表示するために、ページでオブジェクトを取得するpagerオブジェクトのgetResults()メソッドを使用して下さい:



<?php foreach ($pager->getResults() as $article): ?>
  <?php echo link_to($article->getTitle(), 'article/read?id='.$article->getId()) ?>
  <?php echo $article->getOverview() ?>
<?php endforeach ?>

複数のページをまたがってナビゲートする


haveToPaginate()メソッドのおかげでページャオブジェクトは結果の数が一つのページ(例では10)が表示される最大数を超えているかを知っています。


(« < > »)リストの底でナビゲーションリンクを追加するために、getfirstPage()getPreviousPage()getLastPage()などのナビゲーションメソッドを使用して下さい。現在のページはgetPage()によって与えられます。すべてこれらのメソッドは整数を返します: リクエストされたページのランクです。


特定のページを指定するために、getLinks()メソッドへのコールによって取得されるリンクのコレクションを通してループして下さい:



<?php if ($pager->haveToPaginate()): ?>
  <?php echo link_to('«', 'article/list?page='.$pager->getFirstPage()) ?>
  <?php echo link_to('<', 'article/list?page='.$pager->getPreviousPage()) ?>
  <?php $links = $pager->getLinks(); foreach ($links as $page): ?>
    <?php echo ($page == $pager->getPage()) ? $page : link_to($page, 'article/list?page='.$page) ?>
    <?php if ($page != $pager->getCurrentMaxLink()): ?> - <?php endif ?>
  <?php endforeach ?>
  <?php echo link_to('>', 'article/list?page='.$pager->getNextPage()) ?>
  <?php echo link_to('»', 'article/list?page='.$pager->getLastPage()) ?>
<?php endif ?>

これは次のようにレンダーします:


   « < 1 - 2 - 3 - 4 - 5 > »


記事が一旦表示されると、パジネートされたリストに戻ることなく前か次の記事にナビゲーションを導くことを可能になり、カーソルが必要になります。


複数のオブジェクトをまたがってナビゲートする


リストの範囲内にあるページごとにページをナビゲートすることを簡単ですが、ユーザーはオブジェクトごとにオブジェクトをナビゲートするリストに戻ることは望まないでしょう。sfPropelPagerオブジェクトのcursor属性は現在のオブジェクトのオフセットを保持します。


このことによってreadSuccess.phpテンプレートにある記事ナビゲーションごとの記事が可能になります。最初に、listSuccess.phpテンプレートのコードを少し修正しましょう:



<?php $cursor = $pager->getFirstIndice(); foreach ($pager->getResults() as $article): ?>
  <?php echo link_to($article->getTitle(), 'article/read?cursor='.$cursor) ?>
  <?php echo $article->getOverview() ?>
<?php ++$cursor; endforeach ?>

readアクションはcursorパラメータを取り扱う方法を知る必要があります:



class articleActions extends sfActions
{
  public function executeRead()
  {
    ...
    if ($this->getRequestParameter('cursor'))
    {
      $article = $pager->getObjectByCursor($this->getRequestParameter('cursor'));
    }
    else if ($this->getRequestParameter('id'))
    {
      $article = ArticlePeer::retrieveByPK($this->getRequestParameter('id'));
    }

    // エラー
    $this->forward404Unless($article);
  }
}

getObjectByCursor($cursor)メソッドは指定したポジションでカーソルを設定し、まさにそのポジションでオブジェクトを返します。


setCursor($cursor)メソッドでオブジェクトの取得と結果無しにカーソルを設定することが出来ます。カーソルが一旦設定されると、このポジション(getCurrent())での現在のオブジェクトだけでなく、前のもの(getPrevious())と次のもの(getCurrent())を取得することが出来ます。


このことはreadアクションは少しの修正で記事ごとの記事のためにテンプレートと必要な情報に移動することが出来ることを意味します。



class articleActions extends sfActions
{
  public function executeRead()
  {
    ...
    if ($this->getRequestParameter('cursor'))
    {
      $pager->setCursor($this->getRequestParameter('cursor'));
      $previous_article = $pager->getPrevious();
      $article = $pager->getCurrent();
      $next_article = $pager->getNext();
    }
    else if ($this->getRequestParameter('id'))
    {
      $article = ArticlePeer::retrieveByPK($this->getRequestParameter('id'));
    }

    // エラー
    $this->forward404Unless($article);
  }
}

: getPrevious()getNext()メソッドは前もしくは次のオブジェクトが存在しない場合はnullを返します。


readSuccess.phpテンプレートは次のように見えます:



<h1><?php echo $article->getTitle() ?></h1>
<p class="overview"><?php echo $article->getOverview() ?></p>
<div class="content">
  <?php echo $article->getContent() ?>
</div>
< <?php echo link_to_if($previous_article, $previous_article->getTitle(), 'article/read?id='.$previous_article->getId()) ?>
-
> <?php echo link_to_if($next_article, $next_article->getTitle(), 'article/read?id='.$next_article->getId()) ?>

ソートの順番を変更する


sfPropelPagerオブジェクトはCriteriaオブジェクトに依存するので、ページャの順序を変更することはページャオブジェクトに割り当てる前に、クリテリアにソートを追加することでシンプルに行われます。


例えば、ソートカラムの選択をリストナビゲーションインターフェイスに追加することが出来ます:



class articleActions extends sfActions
{
  public function executeList()
  {
    ...
    $c = new Criteria();
    $c->add(ArticlePeer::PUBLISHED, true);
    if ($this->getRequestParameter('sort'))
    {
      $c->addAscendingOrderByColumn(ArticlePeer::translateFieldName($this->getRequestParameter('sort'), BasePeer::TYPE_FIELDNAME, BasePeer::TYPE_COLNAME));
    }
    else
    {
      // デフォルトで日付によってソートされます
      $c->addAscendingOrderByColumn(ArticlePeer::UPDATED_AT);
    }
    $pager = new sfPropelPager('Article', 10);
    $pager->setCriteria($c);
    $pager->init();
    $this->pager = $pager;
    ...
  }
}

listSuccess.phpテンプレートに次のコードを追加します:



Sort by : <?php echo link_to('Title', 'article/list?sort=title') ?> - <?php echo link_to('Id', 'article/list?sort=Id') ?>

ページごとの結果数を変更する


setMaxPerPage($max)メソッドはページャを再処理する必要無しに(init()を再び呼び出す必要がない)ページごとに表示される結果数を変更します。パラメータとして0の値を渡す場合、ページャは一つの単独のページですべての結果を表示します。



class articleActions extends sfActions
{
  public function executeList()
  {
    ...
    $c = new Criteria();
    $c->add(ArticlePeer::PUBLISHED, true);
    $pager = new sfPropelPager('Article', 10);
    $pager->setCriteria($c);
    if ($this->getRequestParameter('maxperpage'))
    {
      $pager->setMaxPerPage($this->getRequestParameter('maxperpage'));
    }
    $pager->init();
    $this->pager = $pager;
    ...
  }
}

listSuccess.phpテンプレートに次のコードを追加します:



Display : <?php echo link_to('10', 'article/list?maxperpage=10') ?> - <?php echo link_to('20', 'article/list?maxperpage=20') ?> results per page

selectメソッドを変更する


sfPropelPagerに依存するアクションのパフォーマンスを最適化する必要がある場合、シンプルなdoSelect()の代わりにdoSelectJoinXXX()を使用するページャを強制したいでしょう。sfPropelPagerオブジェクトのsetPeerMethod()メソッドによって簡単に獲得出来ます:



$pager->setPeerMethod('doSelectJoinUser');

ページを表示するときにページャは実際にdoSelect()クエリを処理することに留意して下さい。最初のクエリ($pager->init()によって引き起こされます)はdoCountをするだけですが、次のコードを呼び出すことでこのメソッドをカスタマイズすることも出来ます:



$pager->setPeerCountMethod('doCountJoinUser');

ページャで追加情報を保存する


ページャオブジェクトである種のコンテキストを保存する必要があるかも知れません。sfPropelPagerクラスが通常の方法でパラメータを処理できる理由はそういうわけです:



$pager->setParameter('foo', 'bar');

if ($pager->hasParameter('foo'))
{
  $pager->getParameter('foo');
  $pager->getParameterHolder()->removeParameter('foo');
}

$pager->getParameterHolder()->clearParameters();

これらのパラメータはけっしてページャによって直接使用されません。


To learn more about custom parameters, refer to the Chapter 2.


Show Markdown text

Menu

Documentation



block contents