PHPメモ ページングの話
新しいことを脳に入れようとすると眠気が襲い来る
SELECTで取ってくる個数の上限を決める文
<?php $sql = 'SELECT * FROM images LIMIT 3 OFFSET 0;
LIMIT
は取ってくる個数 OFFSET
はデータの何番目から取ってくるか
この文の場合は0番目(先頭ですね……)からデータを3つ持ってくる 0番目、1番目、2番目
ページネーションってのは要はこれを元に
<?php $dataNum = 1Pに表示するデータの数; $page = ページ数; $sql = 'SELECT * FROM images LIMIT $dataNum OFFSET ($page - 1) * $dataNum';
で回していく形なんですね
例えば1Pに最大10件表示するとして1P目は
SELECT * FROM images LIMIT 10 OFFSET (1 - 1) * 10
LIMIT
はまぁ常に10として OFFSET
は(1 - 1)が0の時点で何掛けようがゼロ、要は0から10個取ってきてくれる
2P目
SELECT * FROM images LIMIT 10 OFFSET (2 - 1) * 10
(2 - 1) * 10 = 10、1Pは0~9を取っているのでちゃんとその続きですね
3P目
SELECT * FROM images LIMIT 10 OFFSET (3 - 1) * 10
(3 - 1) * 10 = 20、2Pは10~19なので20からで正解
以下続く
そんな理屈
実際にページングを回すときの理屈
今回は最大表示が5のページングを作る仮定でいく
具体的に言うとこういう感じのもの(今イラレで即興で作った)
for文で回す
基本形はこう
<?php $current = 現在のページ数; $minPage = ページネーションの最小数(一番左に表示される数字) $maxPage = ページネーションの最大数(一番右に表示される数字) $minPage = $current - 2; $maxPage = $current + 2; ?> <!-- $i を最小数から最大数まで1つずつ書き出す --> <?php for($i = $minPage ; $i <= $maxPage ; $i++): ?> <!-- URL(GETパラメータ)とリンクに表示させる文字として書き出し --> <li><a href="?p=<?php echo $i ;?>"><?php echo $i; ?></a></li> <?php endfor; ?>
最小と最大の数値の決め方の感覚としては多分この画像がわかりやすい
3つなら±1だし7つなら±3だ
これがまぁ基本
ただまぁ例外がいっぱいあるので以下その場合の対応を書く
現在のページが最大ページ数の -1だった場合
例えば最大ページ数が5で現在のページが4P目だった場合、上のままだと存在しない6P目が表示されてしまう ※総ページ数は 全データ数÷ページごとの表示データ数+(あまりが出た場合1)で計算できます
理想としてはこう(以下の画像)なってほしい
つまり現在のページ数 == 総ページ数 - 1が成立する場合に $minPage = $current - 3, $maxPage = $current + 1 に変えてやる必要がある
<?php $totalPage = 総ページ数; if($current == $totalPage - 1){ $minPage = $current - 3; $maxPage = $current + 1; }
というかここまで書いて(動画を見ながら書いています)残りの理屈がわかってしまったから以下簡単にまとめるわね
現在のページ == 最大ページ数 の場合
<?php if($current == $totalPage){ $minPage = $current - 4; // $total - 1になるはず $maxPage = $current; }
現在のページ == 2 の場合
<?php if($current == 2 ){ $minPage = 1; // $current - 1と同義ではあるが $maxPage = $current + 3 ; }
現在のページ == 1 の場合
<?php if($current == 1 ){ $minPage = $current; // 1と同義 $maxPage = $current + 4 ; }
(※ちょっと重要)最大ページ数がページネーション数より少ない場合
これは自分で気付かなかった点なのですが、総ページ数がページネーション数より少ない場合、上の方法を通すと存在しないページを生成してしまいます
なので上の方法に「総ページ数がページネーション数以上である」という条件を追加しつつ、総ページ数がページネーション未満の場合の分岐も作ってやる
総ページ数がページネーション未満の場合、現在地の位置は関係なく最小は1、最大はページネーション数そのまま、という感じになる
<?php $pageNum = ページネーション数; if( $totalPage < $pageNum ){ $minPage = 1 ; $maxPage = $pageNum ; }
これらを総括して条件分岐を作る
<?php // 現在のページが最大 - 1 if($current == $total - 1 && $totalPage >= $pageNum){ $minPage = $current - 3; $maxPage = $current + 1; } // 現在のページが最大ページ数と等しい elseif($current == $totalPage && $totalPage >= $pageNum){ $minPage = $current - 4; $maxPage = $current; } // 現在のページが最小ページ数の+1=現在のページが2P目 elseif($current == 2 && $totalPage >= $pageNum){ $minPage = $current - 1; $maxPage = $current + 3; } // 現在のページが最小ページ=現在のページが1P目 elseif($current == 1 && $totalPage >= $pageNum){ $minPage = $current; $maxPage = $current + 4; } // ここまで全て最大ページ数がページネーション数以上の場合の条件 // 最大ページ数がページネーション数未満の場合 elseif($totalPage < $pageNum){ $minPage = 1; $maxPage = $pageNum; } // 上記のどれにも該当しない else{ $minPage = $current - 2; $maxPage = $current + 2; }
そんなこんなで最小数、最大数を決めた上でさっきの
<!-- $i を最小数から最大数まで1つずつ書き出す --> <?php for($i = $minPage ; $i <= $maxPage ; $i++): ?> <!-- URL(GETパラメータ)とリンクに表示させる文字として書き出し --> <li><a href="?p=<?php echo $i ;?>"><?php echo $i; ?></a></li> <?php endfor; ?>
を回してやる
結論必要な情報
- 現在のページ
- ページの最大数
- ページネーションで表示されるページ数
- 1ページに表示されるデータの数
※執筆途中です