The symfony Cookbook

リストをページ分割する方法

You are currently browsing
the website for symfony 1

Visit the Symfony2 website


About

You are currently reading "The symfony Cookbook" which is licensed under the Creative Commons Attribution-Noncommercial-No Derivative Works 3.0 Unported License license.

Master symfony

Be trained by SensioLabs experts (2 to 6 day sessions -- French or English).
trainings.sensiolabs.com

Books on symfony

Learn more about symfony with the official guides.
books.sensiolabs.com

L'audit Qualité par SensioLabs

200 points de contrôle de votre applicatif web.
audit.sensiolabs.com

Chapter Content

概要

sfPropelPagerオブジェクト

複数のページを移動する

複数のオブジェクトでのナビゲーション

ソートの順序を変更する

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

selectメソッドを変更する

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

symfony training
Be trained by symfony experts
May 29: Paris (Web Development with Symfony2 - Français)
May 31: Paris (Mastering Symfony2 - Français)
Jun 06: Paris (Introduction to Symfony2 - Français)
Jun 06: Paris (Introduction to Symfony2 - English)
Jun 06: Paris (Going Further with Symfony2 - English)
and more...

Search


powered by google
You are currently browsing "The symfony Cookbook" in Japanese for the 1.1 version - Switch to version: - Switch to language:
Creative Commons License This work is licensed under a Creative Commons Attribution-Noncommercial-No Derivative Works 3.0 Unported License.
Translation of this work into another language is explicitly allowed.
This version of symfony is not maintained anymore.
If some of your projects still use this version, consider upgrading as soon as possible.

概要

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

sfPropelPagerオブジェクト

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

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

ページ分割されていないcriteriaリクエストの結果が欲しい場合、次の内容が必要になります:

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;
    ...
  }
}

このアクションの後で、criteriaの定義の違いの後が違います:

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()メソッドのおかげでページャオブジェクトは1つのページ(例では10)に表示される結果数が最大値を超えているかを知っています。

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

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

<?php if ($pager->haveToPaginate()): ?>
  <?php echo link_to('&laquo;', 'article/list?page='.$pager->getFirstPage()) ?>
  <?php echo link_to('&lt;', '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('&gt;', 'article/list?page='.$pager->getNextPage()) ?>
  <?php echo link_to('&raquo;', 'article/list?page='.$pager->getLastPage()) ?>
<?php endif ?>

これは次のようにレンダリングされます:

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

記事がいったん表示されると、ページ分割されたリストに戻ることなく前か次の記事に直接移動できるので、カーソルが必要になります。

上記のコードはsfPagerNavigationプラグインで自動化されます。インストールと使い方についてもっと詳しい情報は説明ページを参照してください。

複数のオブジェクトでのナビゲーション

リストの範囲内にあるページ単位のナビゲーションは簡単ですが、ユーザーはオブジェクト単位で進むリストに戻ることは望まないでしょう。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>
&lt; <?php echo link_to_if($previous_article, $previous_article->getTitle(), 'article/read?id='.$previous_article->getId()) ?>
-
&gt; <?php echo link_to_if($next_article, $next_article->getTitle(), 'article/read?id='.$next_article->getId()) ?>

ソートの順序を変更する

sfPropelPagerオブジェクトはCriteriaオブジェクトに依存するので、ページャオブジェクトにソートが割り当てられる前に、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();

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

カスタムパラメータをもっと学びたいのであれば、2章を参照してください。

Questions & Feedback

If you find a typo or an error, please register and open a ticket.

If you need support or have a technical question, please post to the official user mailing-list.