初投稿です。
PHPのページネーションに関して、以前実装したものの知識が抜けていたので、アウトプットがてら復習したいと思います。何かのお役に立てれば幸いです。
要件
・各ページで5つずつ表示する
・ページの前後には「前へ」「次へ」を表示。複数ページある場合はリンクになり、それぞれのボタンを押すと前後のページへジャンプする
・ページ番号は5つまで表示。基本的に現在表示されているページの前後2つを表示させる
・ページ数が表示されてる部分にあわせて「○件中○〜○件目の商品」と記載する
なお、今回はLaravelなどのフレームワークは使わずに、生のPHPで実装します。
イメージとしてはこんな感じです。
DB関連
function get_db_connect(){
$dsn = 'mysql:dbname='. DB_NAME .';host='. DB_HOST .';charset='.DB_CHARSET;
try {
$dbh = new PDO($dsn, DB_USER, DB_PASS, array(PDO::MYSQL_ATTR_INIT_COMMAND => 'SET NAMES utf8mb4'));
$dbh->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);
$dbh->setAttribute(PDO::ATTR_EMULATE_PREPARES, false);
$dbh->setAttribute(PDO::ATTR_DEFAULT_FETCH_MODE, PDO::FETCH_ASSOC);
} catch (PDOException $e) {
exit('接続できませんでした。');
}
return $dbh;
}
function fetch_all_query($db, $sql, $params = array()){
try{
$statement = $db->prepare($sql);
$statement->execute($params);
return $statement->fetchAll();
}catch(PDOException $e){
エラーメッセージの表示;
}
return false;
}
①modelで必要な要素をselectで抽出する
$db = get_db_connect();
function get_items_list($db, $limit = 5, $offset = 0){
$sql = '
SELECT
--selectする要素を記載
limit ?
offset ?';
return fetch_all_query($db, $sql, array($limit, $offset));
}
このとき、$limit=5で表示させる件数を予め限定させておく。
また、全体の件数も知っておきたいので、countを使って実装。
function get_items_count($db) {
$sql = '
SELECT
count(*)
FROM
テーブル名'
$result = fetch_all_query($db, $sql);
return $result[0]['count(*)'];
}
②view画面の実装
<?php
foreach($items as $value) {
--ここにget_items_list関数から表示させたいアイテムを表示
}
echo $items_count. '件中'.$page_ini. "〜" .$page_fin. "件目の商品";
// リンクをつけるかの判定
if($now > 1){
print '<a href=\'../html/〜.php?page_id='.($now - 1).'\')>前へ</a>'. ' ';
} else {
print '前へ'. ' ';
}
for($i = 1; $i <= $max_page; $i++){
if($i >= $now - $range && $i <= $now + $range) {
if ($i == $now) {
print '<a class="current_page" href=\'〜.php?page_id='.$now.'\')>'. $now. '</a>'. ' ';
} else {
print '<a href=\'../html/〜.php?page_id='.$i. '\')>'. $i. '</a>'. ' ';
}
}
}
// リンクをつけるかの判定
if($now < $max_page){
print '<a href=\'../html/〜.php?page_id='.($now + 1).'\')>次へ</a>'. ' ';
} else {
print '次へ';
}
?>
まず、〜件中○〜○件目の商品の部分から。
$items_countに関しては、modelで記述したget_items_count関数を使って表示させます。
page_iniとpage_fin(つまり、表示させる商品ページの最初と最後の部分)に関しては、getで取得するページidによって、offsetの値が定義され、それにより表示されるページが変わるといった感じ。
「前へ」「次へ」に関しては、クリックするとgetしたページid+1がgetで渡される。
表示されるページの数に関しては、for文にて表示。
$rangeに関しては、ページidが1、もしくは最後のページのときは4、id=2、最後のページから1つ前のときは3、それ以外は2となるように設定しています。
//ページネーションの表示数
if((int)$now === 1 || (int)$now === (int)$max_page) {
$range = 4;
} else if((int)$now === 2 || (int)$now === ((int)$max_page -1)) {
$range = 3;
} else {
$range = 2;
}
③controllerの記載
viewで指定した変数をそれぞれ定義する。
if(get_get('page_id')) {
$now = $_GET['page_id'];
} else {
$now = 1;
}
$offset = ($now - 1) * 5;
$items = get_items_list($db, $limit = 5, $offset);
$items_count = get_items_count();
$max_page = ceil($items_count / 5);
$page_ini = ($offset + 1);
if(count($items) === 5) {
$page_fin = ($offset + 5);
} else {
$page_fin = $items_count;
}
if((int)$now === 1 || (int)$now === (int)$max_page) {
$range = 4;
} else if((int)$now === 2 || (int)$now === ((int)$max_page -1)) {
$range = 3;
} else {
$range = 2;
}
まずGETで受け取ったページidを定義する(get_getはユーザー定義関数)
//viewからのidをgetしたとき
if(get_get('page_id')) {
$now = $_GET['page_id'];
} else {
//設定されてない場合は1ページ目にする
$now = 1;
}
定義したら、その変数($now)を使ってoffsetを定義する
//ここでoffsetの定義
$offset = ($now - 1) * 5;
modelで実装したselect文もここで定義しておく。
$items = get_items_list($db, $limit = 5, $offset);
$items_count = get_items_count();
ceil関数を使って、小数点になる場合は繰り上げを行う。
$max_page = ceil($items_count / 5);
前述の通り、page_iniとpage_fin(つまり、表示させる商品ページの最初と最後の部分)に関しては、offsetの値により表示されるページが変わる。
//最初
$page_ini = ($offset + 1);
//最後(1ページに表示されるアイテム数が5つの場合とそうでない場合で条件分岐)
if(count($items) === 5) {
$page_fin = ($offset + 5);
} else {
$page_fin = $items_count;
}
あとはLaravelでもページネーションを実装してみたいな。