PHP 備忘録 | メシのタネ

pagenateu
このエントリーをはてなブックマークに追加

【PHP】ページネートを理解する

 2014/05/30

たまに作る機会があって、ある度に何だっけってなるので
何時見ても大丈夫なように残しておこうと思います。
量がドッサリなので、アンカーつけと来ます。

もくじ

アウトライン

ページネートって何
仕組み

ページ出力プログラム

ページ総数、始点、終点を求める
ページ数の出力処理
次へと前へも付けたい

データ出力プログラム

データ出力のプログラム

まとめ

主要部分の計算結果のまとめ
コード全文

ページネートって何

呼び名が色々ある気がします。
僕が働いてる所では、これを明細といいますし、
ページャーやページ送りと言ってるページも見かけます。
言い方ばらばらですが、僕は最初に聞いたのがページネートなので
ページネートって言ってます。

仕組み

あるデータの総件数を表示させる行数で割り総ページ数を計算します。
次に表示させたいページ数から始点と終点の値を設定し
それを元に明細を表示させます。

ページネートは表示させたいページ数から始点と終点の値を設定して
始点から終点までの値を出力するプログラムの事だと思います。

pagenate

要はこんなやつですね。

準備

今回はデータベースからデータ抜いてこずに
自前でデータ入れた配列を準備します。
後はgetのサニタイズとかです。
関係ない部分なので特に言いたいことはありません。


$data = array();
define("num", 236);

function gcheck($d)
{
     if(empty($d))
     {
          $page = 1;
          return $page;
     } else {
          $esc = htmlspecialchars($d,ENT_QUOTES);
          $page = (int)$esc;
          if(empty($page))
          {
               gcheck($page);    
          } else {
               return $page;
          }         
     }
}

for($i=0; $i<num; $i++)
{
     $data[] = rand(0,1000);
}

$count=num; 

countにnum入れてますが、別に入れずにそのままnum使っても良いです。

一旦もどる

ページ総数、始点、終点を求める

まずソース

define("row",15); //表示したいデータの行数
define("splitnum",5); //表示したいページ数

$page = gcheck($_GET["getpage"]);
$max = $count%row == 0 ? (int)$count/row : (int)ceil($count/row);
$sp = $page>splitnum/2 ? $page-floor(splitnum/2): 1;
$gp = $sp+(splitnum-1);

三項演算子

条件式を真、偽判断できます。
書き方は
条件式 ? 真の場合 : 偽の場合 ;
って書き方ができるのでコードが短くなります。

ページ総数の計算方法

データ総件数とデータ表示件数を割った場合のあまり(剰余)を求めます。
あまりが0であった場合、データ件数割るデータを表示する数を求めます。
そうでない場合、データ件数割るデータを表示する数を求めた後に切り上げます。

始点の計算方法

現在アクティブなページ数が「表示したいページ数の半分」よりも多い場合
現在ページから「表示したいページ数の半分の小数点を切り捨てた数」
そうじゃない場合は1になります。

終点の計算方法

始点の数と表示したいページ数から1を引きます。

表示したいページ数が5で、現在ページが1の場合は?

なんか分かりにくいので、例を出します。

始点の計算

1>5/2これを比較すると値は2.5になります。
1>2.5は正しくないので、答えは偽になります。
偽の時に代入される値は1です。

終点の計算

始点の計算結果と(表示したいページ数を1引いた数)です。

何で1引くのかといえば、今回は5ページ出したいので
[始点][..][..][..][終点]としたい訳です。
始点は決まった状態で終点の結果を求めるので、
もしこれを1引かずにやると
[始点][..][..][..][..][終点]こうなります。
こうならないために-1する必要があります。

だから表示したいページ数が5で、現在ページが1の場合は
[1][2][3][4][5]っていう風になります。

一旦もどる

表示したいページ数が5で、現在ページが3の場合は?

始点の計算

3>5/2これを比較すると値は2.5になります。
3>2.5は正しいので、答えは正になります。
正の時に代入される値は現在のページ数-1です。
なので、3-1でこの場合2が始点になります。

終点の計算

終点の計算方法はさっきとおんなじです。
始点の計算結果+(表示したいページ数-1)なので
2+(5-1) = 6になり、終点は6になります。

始点と終点が決まったので、
[2][3][4][5][6]という結果になります。

終点がページ総数より大きくなると困る

このままだと終点の値がページ総数を越えて、
ユーザーの根性次第で一生ページは進み続けます。
そんな人多分居ませんけど、こうなると困るので条件分岐をします。


if($gp>$max)
{
     $gp = $max;
}

このように、終点がページ総数超えた場合には
終点をページ総数にしてしまいましょう。

ページ数の出力処理

さっきからやってる感じで値をとっておけば、
ただfor回すだけで終わります。


for($i=$sp; $i<=$gp; $i++)
{
     if($page == $i) //現在ページ数にクラスをつけるための条件分岐だよ!
     {
          echo "<a class=\"active\" href=\"?getpage=".$i."\">".$i."</a>&nbsp;";
     } else {
          echo "<a href=\"?getpage=".$i."\">".$i."</a>&nbsp;";
     }
}

一旦もどる

次へと前へも付けたい

数字だけ出ても仕方ないので、次へと前へもつけてみます。


$next = $page+1<=$max ? $page+1 : false;
$prev = $page-1<0 ? false : $page-1;

現在のページ数を足してもまずくない場合と引いてもまずくない場合を評価します。
評価のやり方は、まず現在のページから足してみるor引いてみるを行って、
次へなら、現在のページ数がページ総数より多いか否かで判断し
前へなら、現在ページ数が0よりも少ないかを判断します。

が条件はこれ以外にも色々実現する方法があると思います。
これを設定した後に


if($prev)
{
     echo "<a href=\"?getpage=".$prev."\">&laquo; 前へ</a>";
}

for($i=$sp; $i<=$gp; $i++)
{
     if($page == $i)
     {
          echo "<a class=\"active\" href=\"?getpage=".$i."\">".$i."</a>&nbsp;";
     } else {
          echo "<a href=\"?getpage=".$i."\">".$i."</a>&nbsp;";
     }
}

if($next)
{
     echo "<a href=\"?getpage=".$next."\">次へ &raquo;</a>";
}

こうしてやればオッケーです。

データ出力のプログラム

ここから出力プログラムの説明になります。

行数の始点、終点の決定


$loc = $page-1<0 ? 1 : $page-1;
$getstart = $loc*row;
$getend = row-1+$getstart;


行数始点の計算方法

始点の計算方法は、現在ページ数-1*表示行数で求めることができます。
ページ数-1すると0になる場合があるので、条件判断して
代入する値を変えたものをlocに入れています。

表示行数が15件なら

現在ページが1の場合に0
現在ページが2の場合に15
と始点がアガっていきます。

行数終点の計算方法

表示したい行数-1+行数始点の計算結果これで求めることが出来ます。

表示行数が15件なら

現在ページが1の場合に14
現在ページが2の場合に29
と終点がアガっていきます。

終点がデータ総件数を超えた場合

これも、ページ総数の所でやりましたけど、

if($getend>$count)
{
     $getend = $count-1;
}

終点を越えたらこうします。
countが-1されるのは配列は0から始まるので
1件多くカウントされちゃうからです。

一旦もどる

出力

for($i = $getstart; $i<=$getend; $i++)
{
     echo "<div style=\"margin-top: 20px;\">".$data[$i]."</div>";
}

特になし。

主要部分の計算結果のまとめ

ページ出力

ページ総数

データ総数%表示行数 == 0 ? データ総数/表示行数 : 端数切捨て(データ総数/表示行数)+1 ;

始点位置

現在ページ数 > 表示ページ総数 ? 現在ページ数- 端数切捨て(表示ページ総数/2) : 1;

終点位置

始点計算結果+(表示ページ数 – 1)

データ出力

行数の始点

現在ページ-1 < 0 ? 1 : 現在ページ-1; ↑の結果*表示したい行数 行数の終点 表示したい行数-1+行数の始点

コード全文

<?php
$data = array();
define("num", 150);

function gcheck(&$page)
{
	if(empty($page))
	{
		$page = 1;
		var_dump($page);
		return $page;
	} else {
		$esc = htmlspecialchars($page,ENT_QUOTES);
		$page = intval($esc);
		if(empty($page))
		{
			gcheck($page);	
		} else {
			return $page;
		}		
	}
}

for($i=0; $i<num; $i++)
{
	$data[] = rand(0,1000);
}

$count=num; 

define("row",15);
define("splitnum",5);
$page = $_GET["getpage"];
gcheck($page);

$max = $count%row == 0 ? intval($count/row) : intval(ceil($count/row));
$sp = $page>splitnum/2 ? intval($page-floor(splitnum/2)): 1;
$gp = $sp+(splitnum-1);

if($gp>$max)
{
	$gp = $max;
}

$next = $page+1<=$max ? $page+1 : false;
$prev = $page-1<0 ? false : $page-1;

if($prev)
{
	echo "<a href=\"?getpage=".$prev."\">&laquo; 前へ</a>";
}

for($i=$sp; $i<=$gp; $i++)
{
	if($page == $i)
	{
		echo "<a class=\"active\" href=\"?getpage=".$i."\">".$i."</a>&nbsp;";
	} else {
		echo "<a href=\"?getpage=".$i."\">".$i."</a>&nbsp;";
	}
}

if($next)
{
	echo "<a href=\"?getpage=".$next."\">次へ &raquo;</a>";
}

$loc = $page-1<0 ? 1 : $page-1;
$getstart = $loc*row;
$getend = row-1+$getstart;
$scount = $loc*row+1;
$gcount = row-1+$getstart+1;


if($getend>$count)
{
	$getend = $count-1;
}

if(!empty($count))
{
	echo "<div style=\"margin-top: 20px;\">".$page."ページ目 ".$scount."-".$gcount."件目まで表示</div>";
}


for($i = $getstart; $i<=$getend; $i++)
{
	echo "<div style=\"margin-top: 20px;\">".$data[$i]."</div>";
}




?>

<style>
.active{
	color: red;
}
</style>


このエントリーをはてなブックマークに追加

コメント

"【PHP】ページネートを理解する"
でメシのタネのおすすめを検索したよ!

プログラミング備忘録 | メシのタネ