まぁ作ってみたというか、使っているやつなんですけども。
はてブ見てたら上記のようなページング処理関する話題がでていたので、僕も公開してみます。ちなみに、上記のものとは処理というか設計思想が違うので改良版とか考察とかではありません(^^;
クラスは以下。公開用でこれだけでとりあえず動くようにするために一部簡素化しているので、エスケープ処理とか適当に入れて使うと良いと思います。
class Pager { var $query; // ページを示すキー var $rowCount; // 1ページあたりの件数 var $max; // 総件数 private $get = array(); // 引数の配列 private $page; // 現在のページ番号 private $href; // 引数なしのurl部分 private $pageCount; // 総ページ数 /*-------------------------------------------------- * * コンストラクタ * @param ページを示すキー : string * 1ページあたりの件数 : int * 総件数 : int * --------------------------------------------------*/ public function __construct( $query, $rowCount, $max ) { $this->query = $query; $this->rowCount = $rowCount; $this->max = $max; // URLとクエリを設定 $this->setRequestUri(); $this->page = ( isset( $this->get[$query] ) ) ? $this->get[$query] : '1'; $this->pageCount = ceil( $this->max / $this->rowCount ); } /*-------------------------------------------------- * * URLとクエリを取得、設定 * --------------------------------------------------*/ protected function setRequestUri () { $requestUri = explode( '?', $_SERVER['REQUEST_URI'] ); $this->href = $requestUri[0]; $this->get = $_GET; } /*-------------------------------------------------- * * ページャhtml生成 * @param array( * 'size' => 表示する数字の個数, : int * 'firstMark' => 最初の記号, : string * 'prevMark' => 前の記号, : string * 'nextMark' => 次の記号, : strng * 'lastMark' => 最後の記号 ) : string * @return html : string * --------------------------------------------------*/ public function getPager( $_arr = array() ) { $_ret = ''; if ( $this->rowCount ) { // 引数の初期値 $default = array( 'size' => $this->pageCount, 'firstMark' => '<<', 'prevMark' => '<', 'nextMark' => '>', 'lastMark' => '>>', ); // パラメータを結合し決定 $_arr = array_merge( $default, $_arr ); $diff = floor( $_arr['size'] / 2 ); // 1ページしか無いときは出さない if ( $this->pageCount > 1 ) { // 最初のページ、前のページ if ( $this->page > 1 ) { // 最初のページ $_ret .= $this->getLink ( 1, $_arr['firstMark'] ); // 前のページ $_ret .= $this->getLink ( $this->page - 1, $_arr['prevMark'] ); } // 繰り返し部分 if ( $this->page + $diff > $this->pageCount ) { $start = $this->pageCount - $_arr['size'] + 1; $start = ( $start < 0 ) ? 1 : $start; $end = $this->pageCount; } elseif ( $this->page <= $diff ) { $start = 1; $end = $start + $_arr['size'] - 1; } else { $start = $this->page - $diff; $end = $start + $_arr['size'] - 1; } for ( $i = $start; $i <= $end; $i ++ ) { if ( $this->page == $i ) { $_ret .= '<span class="current">'.$i.'</span> '; } else { $_ret .= $this->getLink ( $i, $i ); } } // 次のページ、最後のページ if( $this->page < $this->pageCount ){ // 次のページ $_ret .= $this->getLink ( $this->page + 1, $_arr['nextMark'] ); // 最後のページ $_ret .= $this->getLink ( $this->pageCount, $_arr['lastMark'] ); } // 出力タグ $_ret = ' <p> '.$_ret.' </p> '; } } return $_ret; } /*-------------------------------------------------- * * リンク要素を生成 * @param ページ番号:num * リンクさせる文字列:string * @return リンク要素 * --------------------------------------------------*/ protected function getLink ( $pageNum, $disp ) { $get = $this->get; $get[$this->query] = $pageNum; $_ret .= '<a href="'.$this->href.'?'.http_build_query( $get ).'">'.$disp .'</a> '; return $_ret; } }
具体的に説明すると、まずインスタンス化するときに、「ページ名を表すクエリの名前」と「1ページに表示する件数」と「総件数」を渡します。で、htmlを生成するメソッドを実行するときにはページャのリンクの個数とか次への文字列とかオプションを指定します。
リンク要素を生成する繰り返し処理の部分なんかはごちゃごちゃしてしまっているのでもう少しスッキリさせる良い計算方法があるかもしれませんね。
ちなみに、CSSも使い回しているものがあるので載せておきます。色の指定を返るくらいで汎用的に使えると思います。
/* .pager ----------------------------------------*/ .pager{ font-size:10px; padding:20px 0; } .pager p{ display:block; margin:0; padding:0; overflow:hidden; _zoom:1; } .pager p span, .pager p a{ color:#111; background-color:#fff; margin:0 2px 0 0; padding:2px 0 1px 0; border:#ddd solid 1px; float:left; width:23px; text-align:center; text-decoration:none; overflow:hidden; } .pager p a:hover, .pager p span.current{ color:#fff; background-color:#ccc; }
で、こんな感じで表示されます。