【PHP】Pagination(ページネーション)を作ってみた!!!
今回は、長いコンテンツやページを分割する際に使われる「ページネーション」を作っていきたいと思います。
完成品
5データごとにページを変える
7をクリックすると
ソースコード
<!DOCTYPE html> <html lang="ja"> <head> <meta charset="UTF-8"> <meta http-equiv="X-UA-Compatible" content="IE=edge"> <meta name="viewport" content="width=device-width, initial-scale=1.0"> <title>Document</title> <link href="style.css" rel="stylesheet"> </head> <body> <?php //db接続処理 try { $db = new PDO('mysql:dbname=testing;host=localhost;charset=utf8', 'root', 'root'); } catch (PDOException $e) { echo 'DB接続エラーが起こりました。'. $e->getMessage(); } if (isset($_GET['page'])) { $page=$_GET['page']; if ($page>=7) { //1〜6ページの時はページネーションが1〜10 //7ページ目は2〜11になる → 7-5 と 7+4 //8ページ目は3〜12になる → 8-5 と 8+4 $page_first = $page - 5; $page_last = $page + 4; } } else { $page=1; } //全データ数を取得 $count_data = $db->prepare("SELECT COUNT(*) FROM pagination"); $count_data->execute(); $count_data = $count_data->fetch(PDO::FETCH_COLUMN); //5個ずつ表示する $pagination=5; //ページごとのデータのヘッドのインデックス $page_per_data_head = $pagination*($page-1); //必要なページ数を計算 $pages = ceil($count_data/$pagination); //LIMIT0、10 の意味は 1番目のデータから10個データを取得する。 //0が1というのは配列のインデックスと同じイメージです。 $comments = $db->prepare("SELECT comment FROM pagination LIMIT ?,5"); $comments->bindParam(1, $page_per_data_head, PDO::PARAM_INT); $comments->execute(); $comments_list = $comments->fetchAll(PDO::FETCH_ASSOC); ?> <!--コメント表示--> <div class="comment_area"> <?php foreach ($comments_list as $comment) { ?> <p><?php echo $comment['comment']; ?></p> <br> <?php } ?> </div> <!--10ページ以下だった場合は全て表示--> <div class="pagination_area"> <?php if ($pages<=10) {?> <?php for ($i=1;$i<=$pages;$i++) { ?> <a href="http://localhost:8888/pagination/index.php?page=<?php echo $i ?>"><?php echo $i ?></a> <?php } ?> <!--10ページより多かった、かつ現在6ページ以下の場合--> <?php } elseif ($pages>10&&$page<=6) {?> <?php for ($i=1;$i<=10;$i++) { ?> <a href="http://localhost:8888/pagination/index.php?page=<?php echo $i ?>"><?php echo $i ?></a> <?php } ?> <!--10ページより多かった、かつ現在6ページより大きい場合--> <?php } elseif ($pages>10&&$page>6) { if ($page_last>=$pages) { $page_last = $pages; } ?> <?php for ($i=$page_first;$i<=$page_last;$i++) { ?> <a href="http://localhost:8888/pagination/index.php?page=<?php echo $i ?>"><?php echo $i ?></a> <?php } ?> <?php } ?> </div> </body> </html>
コードの説明
データベースの接続
//db接続処理 try { $db = new PDO('mysql:dbname=testing;host=localhost;charset=utf8', 'root', 'root'); } catch (PDOException $e) { echo 'DB接続エラーが起こりました。'. $e->getMessage(); }
テーブルのデータ数を取得
//全データ数を取得 $count_data = $db->prepare("SELECT COUNT(*) FROM pagination"); $count_data->execute(); $count_data = $count_data->fetch(PDO::FETCH_COLUMN);
SQLのCOUNT(*)で行数をカウントして、fetchして、COUNT(*)カラムの最初の行の値を取得して、その値を$count_dataに入れる。
1ページに表示するデータ数を指定
//5個ずつ表示する $pagination=5;
$paginationに代入する。
必要なページ数を計算する
$pages = ceil($count_data/$pagination);
先ほど計算したデータ数である$count_dataを、$paginationで割り、必要なページ数を計算し、その値を$pagesに入れる。例えば4.1だった場合、5ページ必要なのでceil()関数を使い切り上げを行う。
5個データを抽出する
$comments = $db->prepare("SELECT comment FROM pagination LIMIT ?,5"); $comments->bindParam(1, $page_per_data_head, PDO::PARAM_INT); $comments->execute(); $comments_list = $comments->fetchAll(PDO::FETCH_ASSOC);
SQLのLIMITについて、プログラミングにおける配列をイメージする。例えば1個目のデータから5つデータを抽出する場合 " LIMIT 0,5 "と 指定する。つまり1ページ目のデータはLIMIT 0,5と指定し、2ページ目のデータはLIMIT5,5、3ページ目のデータはLIMIT10,5とSQLを指定する。つまり第二引数は5固定で第一引数は以下のコードのように指定する。
$page_per_data_head = $pagination*($page-1);
5データずつページを区切るので、$paginationの値は5、に現在いるページ数から1引いたものをかけることによって第一引数を求めることができる。
ページネーションのリンクの設定
if (isset($_GET['page'])) { $page=$_GET['page']; if ($page>=7) { //1〜6ページの時はページネーションが1〜10 //7ページ目は2〜11になる → 7-5 と 7+4 //8ページ目は3〜12になる → 8-5 と 8+4 $page_first = $page - 5; $page_last = $page + 4; } } else { $page=1; }
URLのパラメータpageの値を$pageに代入する。
もし7ページだった場合、
7-5=2 3 4 5 6 7 8 9 10 11=7+4
もし8ページだった場合、
8-5=3 4 5 6 7 8 9 10 11 12=8+4
になるようにするため、数列の最初と最後の値を$page_first、$page_lastに代入する。
ページネーションのリンク表示①
<?php if ($pages<=10) {?> <?php for ($i=1;$i<=$pages;$i++) { ?> <a href="http://localhost:8888/pagination/index.php?page=<?php echo $i ?>"><?php echo $i ?></a> <?php } ?> <!--10ページより多かった、かつ現在6ページ以下の場合--> <?php } elseif ($pages>10&&$page<=6) {?> <?php for ($i=1;$i<=10;$i++) { ?> <a href="http://localhost:8888/pagination/index.php?page=<?php echo $i ?>"><?php echo $i ?></a> <?php } ?>
ページネーションのリンク表示②
<?php } elseif ($pages>10&&$page>6) { if ($page_last>=$pages) { $page_last = $pages; } ?> <?php for ($i=$page_first;$i<=$page_last;$i++) { ?> <a href="http://localhost:8888/pagination/index.php?page=<?php echo $i ?>"><?php echo $i ?></a> <?php } ?> <?php } ?>
$page_lastを$page + 4で求めましたが、$pageの数によっては必要なページ数である$pagesを超える場合があります。
そのため
if ($page_last>=$pages) { $page_last = $pages; } ?>
を記述し、$page_lastが$pagesを超えた場合に、$page_lastを$pagesの値にします。こうすることで無限にページネーションのリンクが出現することを防ぎます。