PHPでページング(ページ送り)を簡単に実装
PHPで簡単にページング(ページ送り)を実装するクラスを作成しました。
ページング処理は、単純に「次へ」「前へ」のみなら簡単なのですが、「最初へ」「最後へ」「前後へ」などをすべて実装使用とすると中々に面倒です。
そんな面倒な設定を一括で設定できるPHPのクラス「Paging」を是非ご活用ください。
参考 PHPのクラスを解説
まずはサンプルをご確認ください
ページング処理を施したページをiframeで呼び出したものです。
全体47件のうち5件を表示させています。
実際に動作をご確認ください。
通常の「前へ」「次へ」に加えて、「現在見ているページ番号の2つ前後」と「最初」と「最後」も備わっているため、移動がしやすい仕組みになっています。
ページングクラス「Paging」
ソースコード
こちらがページングを一括管理するクラスになります。
細かい処理の仕組みなんていいからとにかく実装したい!って方は前半のプロパティ設定だけご確認ください。
/*
MIT License
copyright:kinocolog.com
解説:https://kinocolog.com/php_paging/
*/
class Paging{
//表示させる件数
public $count = 50;
//ページングのパラメータ $_GET[]に入る部分
public $param = 'page';
//現在のページの前後に表示させる数
public $items = 2;
//最初と最後に繋ぐ文字
public $between_str = '…';
//「前へ」にあたる文字
public $prev_str = '≪';
//「次へ」にあたる文字
public $next_str = '≫';
//ulに付くclass
public $ul_class = 'paging';
//aタグを除外する $_GETではなくajax等の処理に
public $atag_remove_flg = false;
public $page = 1;
public $url = '';
public $html = '';
//HTMLを生成 プロパティhtmlに代入
public function setHtml($sum = 0){
$this -> getPage();
$max_page = ceil($sum / $this -> count);
if($max_page == 1 || 1 > $this -> page || !is_numeric($this -> page)){
$this -> page = 1;
}
if($this -> page > $max_page){
$this -> page = $max_page;
}
$aryCmp = [];
for($i = 1; $i <= $max_page; $i++){
$aryCmp[$i] = true;
}
$loop_count = 0;
for($i = ($this -> page + 1); $i <= $max_page; $i++){
$loop_count++;
if($loop_count > $this -> items && $i != $max_page){
unset($aryCmp[$i]);
}
}
$loop_count = 0;
for($i = ($this -> page - 1); $i >= 1; $i--){
$loop_count++;
if($loop_count > $this -> items && $i != 1){
unset($aryCmp[$i]);
}
}
$aryResult = [];
foreach($aryCmp as $key => $value){
$aryResult[] = $key;
if($max_page == $key){
break;
}
if(!isset( $aryCmp[($key + 1)] ) && $this -> between_str){
$aryResult[] = $this -> between_str;
}
}
if(!$aryResult){
return '';
}
$html = '';
$html .= '<ul class="'.$this -> ul_class.'">';
$aryList = [];
if($this -> page != 1 && $this -> prev_str){
$aryList[] = '<li>'.$this -> getQuery(($this -> page - 1), $this -> prev_str).'</li>';
}
foreach($aryResult as $key => $value){
if(is_numeric($value)){
$aryList[] = '<li>'.$this -> getQuery($value, $value).'</li>';
}else{
$aryList[] = '<li>'.$this -> getQuery(0, $value).'</li>';
}
}
if($this -> page != $max_page && $this -> next_str){
$aryList[] = '<li>'.$this -> getQuery(($this -> page + 1), $this -> next_str).'</li>';
}
$this -> html = '<ul class="'.$this -> ul_class.'">'.implode('', $aryList).'</ul>';
}
//現在のページURLを取得 atag_remove_flgがtrueの場合は行わない
private function getPage(){
if($this -> atag_remove_flg) return;
if(isset($_GET[$this -> param]) && is_numeric($_GET[$this -> param])){
$this -> page = $_GET[$this -> param];
}else{
$this -> page = 1;
}
}
//ページ内リンクを生成
private function getQuery($page, $str){
$url = $this -> url;
if(!$url){
$url = ((isset($_SERVER['HTTPS'])) ? 'https://' : 'http://') . $_SERVER['HTTP_HOST'] . $_SERVER['REQUEST_URI'];
if(isset($_SERVER['QUERY_STRING'])){
$url = str_replace('?'.$_SERVER['QUERY_STRING'], '', $url);
}
}
$html = '';
if($this -> page == $page){
return '<span class="active">'.$str.'</span>';
}
if($page == 0){
return '<span class="between">'.$str.'</span>';
}
if(!$this -> atag_remove_flg){
$aryQuery = [];
if($_GET){
$aryQuery = $_GET;
}
$aryQuery[$this -> param] = $page;
if($page == 1){
unset($aryQuery[$this -> param]);
}
if($aryQuery){
return '<a href="'.$url.'?'.http_build_query($aryQuery).'">'.$str.'</a>';
}else{
return '<a href="'.$url.'">'.$str.'</a>';
}
}else{
return '<span data-page="'.$page.'">'.$str.'</span>';
}
}
}
CSS
サンプルで使用したページングのcssデザインはこちらです。
お好みで改造してください。
ul.paging{
list-style-type: none;
margin: auto;
padding: 0;
/* 中央寄せ */
display: table;
/* 左寄せ */
/* display: block; */
/* 右寄せ */
/* display: table; */
/* margin: 0 0 0 auto; */
}
ul.paging::after{
content: "";
display: block;
clear: both;
}
ul.paging > li{
float: left;
}
ul.paging > li > *{
margin: 2px;
padding: 3px 0;
display: block;
color: #000;
text-decoration: none;
}
ul.paging > li > a, ul.paging > li > .active, ul.paging > li > [data-page]{
padding: 3px 10px;
border: 1px solid #CCC;
border-radius: 5px;
}
ul.paging > li > .active{
background-color: #CCC;
}
ul.paging > li > [data-page]{
cursor: pointer;
}
使い方
上記のクラスを記述した上で(別ファイルにしてinclude等で読み込むと楽です)、Pagingのオブジェクトを生成します。
include_once("Paging.php");
//オブジェクトを生成
$pageing = new Paging();
//1ページ毎の表示数を設定
$pageing -> count = 5;
//全体の件数を設定しhtmlを生成
$pageing -> setHtml(47);
//ページングクラスを表示
echo $pageing -> html;
setHtmlメソッドから、$_GET['page']に入った値で現在のページNoを取得し(ない場合は一律で1)、結果以下のようなリストのHTMLを生成します。
<ul class="paging">
<li><span class="active">1</span></li>
<li><a href="https://example.com/?page=2">2</a></li>
<li><a href="https://example.com/?page=3">3</a></li>
<li><span class="between">…</span></li>
<li><a href="https://example.com/?page=10">10</a></li>
<li><a href="https://example.com/?page=2">≫</a></li>
</ul>
現在のページが5ページ目なら前後2ページずつ表示となります。
<ul class="paging">
<li><a href="https://example.com/?page=4">≪</a></li>
<li><a href="https://example.com/">1</a></li>
<li><span class="between">…</span></li>
<li><a href="https://example.com/?page=3">3</a></li>
<li><a href="https://example.com/?page=4">4</a></li>
<li><span class="active">5</span></li>
<li><a href="https://example.com/?page=6">6</a></li>
<li><a href="https://example.com/?page=7">7</a></li>
<li><span class="between">…</span></li>
<li><a href="https://example.com/?page=10">10</a></li>
<li><a href="https://example.com/?page=6">≫</a></li>
</ul>
プロパティオプション
ページングのリストを表示させる上での各種設定です。
//表示させる件数 public $count = 50; //ページングのパラメータ $_GET[]に入る部分 public $param = 'page'; //現在のページの前後に表示させる数 public $items = 2; //最初と最後に繋ぐ文字 public $between_str = '…'; //「前へ」にあたる文字 public $prev_str = '≪'; //「次へ」にあたる文字 public $next_str = '≫'; //ulに付くclass public $ul_class = 'paging'; //aタグを除外する $_GETではなくajax等の処理に public $atag_remove_flg = false;
変更を加えたい場合は、クラスのプロパティ初期値を直接書き換えるか、オブジェクトを生成後、プロパティを代入してください。
//オブジェクトを生成 $pageing = new Paging(); //1ページ毎の表示数を設定 $pageing -> count = 5;
ダウンロードはこちら
Pagingクラスを書いたphpファイルとサンプルで使用したcssファイルをzipにまとめました。
ダウンロードしてご利用ください。
PDOでデータベーステーブルをページング
紹介したクラス「Paging」を使用することで、データベースから指定件数ごとにページ送り機能を作ることが出来ます。
今回は、「pref」という47都道府県のデータが入ったシンプルなものをページ送りすると仮定した時の処理を書いていきます。
要するに、上述のサンプルで使用した処理です。
| 使用するテーブル「pref」 | |
|---|---|
| pref_id | pref_name |
| 1 | 北海道 |
| 2 | 青森県 |
| 3 | 岩手県 |
| … | … |
PHP
$_GETから現在のページ番号を取得し、5件ごと表示させます。
//PDOオブジェクトの生成記述は環境毎に異なるので省略
include_once('Paging.php');
//ページ毎の件数を設定
$row_count = 5;
//テーブル全体の件数を取得
$sql = "SELECT COUNT(*) FROM pref";
$sth = $pdo -> query($sql);
$count = $sth -> fetch(PDO::FETCH_COLUMN);
//現在のページを取得 存在しない場合は1とする
$page = 1;
if(isset($_GET['page']) && is_numeric($_GET['page'])){
$page = (int)$_GET['page'];
}
if(!$page){
$page = 1;
}
//$pageの数から件数分を表示するSQLクエリを生成 配列で取得
$sql = "SELECT * FROM pref";
$sql .= " ORDER BY pref_id LIMIT ".(($page - 1) * $row_count).", ".$row_count;
$sth = $pdo -> query($sql);
$aryPref = $sth -> fetchAll(PDO::FETCH_ASSOC);
//Pagingクラスを生成し、ページングのHTMLを生成
$pageing = new Paging();
$pageing -> count = $row_count;
$pageing -> setHtml($count);
HTML
取得したデータの配列をforeachで回し、リスト化します。
最後に、ページングクラスからsetHtml()で生成したHTMLを出力しています。
<ul>
<?php foreach($aryPref as $value){ ?>
<li><?php echo $value['pref_name']; ?></li>
<?php } ?>
</ul>
<?php echo $pageing -> html ?>
結果、データベースから件数毎にページング処理が出来ていることが確認できます。
AJAXでPOSTするページング
ajaxを使用して、ページ遷移をせずページ内からページング処理を施すことが出来ます。
参考 jQueryでAjax通信を行う方法【サンプルコードで解説】
PHP(ajax取得先)
ajaxで取得するPHPの設定です。
//PDOオブジェクトの生成記述は環境毎に異なるので省略
include_once('Paging.php');
//ページ毎の件数を設定
$row_count = 5;
//テーブル全体の件数を取得
$sql = "SELECT COUNT(*) FROM pref";
$sth = $pdo -> query($sql);
$count = $sth -> fetch(PDO::FETCH_COLUMN);
//現在のページを取得 存在しない場合は1とする
$page = 1;
if(isset($_POST['page']) && is_numeric($_POST['page'])){
$page = (int)$_POST['page'];
}
if(!$page){
$page = 1;
}
//$pageの数から件数分を表示するSQLクエリを生成 配列で取得
$sql = "SELECT * FROM pref";
$sql .= " ORDER BY pref_id LIMIT ".(($page - 1) * $row_count).", ".$row_count;
$sth = $pdo -> query($sql);
$aryPref = $sth -> fetchAll(PDO::FETCH_ASSOC);
//Pagingクラスを生成し、ページングのHTMLを生成
$pageing = new Paging();
$pageing -> count = $row_count;
//Ajax用の処理 aタグを消してdata-page属性を表示させる
$pageing -> atag_remove_flg = true;
$pageing -> page = $page;
$pageing -> setHtml($count);
$html = '';
$html .= '<ul>';
foreach($aryPref as $value){
$html .= '<li>' . $value['pref_name'] . '</li>';
}
$html .= '</ul>';
$html .= $pageing -> html;
echo $html;
HTML
<!-- 取得結果の反映 -->
<div class="ajax_result"></div>
<script>
$(function(){
getList(1);
//ページングのクリックイベント
$(document).on('click', '[data-page]', function(){
var page = Number($(this).data('page'));
getList(page);
});
function getList(page){
$.ajax({
url: '/ajax/pref_paging.php',
type: 'POST',
dataType: 'html',
data : {
page : page
}
}).done(function(data){
/* 通信成功時 */
$('.ajax_result').html(data); //取得したHTMLを.ajax_resultに反映
}).fail(function(data){
/* 通信失敗時 */
});
}
});
</script>
こちらはAjaxなのでブラウザのリロードなしでページング処理が行えます。
PHPでページング処理を行いたい場合に利用できるクラスの紹介でした。
クラスの使い方さえ理解したら、簡単にページングを実装できるので是非お試しください。
以上、PHPでページング(ページ送り)を簡単に実装、でした。

ディスカッション
コメント一覧
現在PHPを勉強しているものです。古い記事にコメント申し訳ありません。
「PDOでデータベーステーブルをページング」の部分でご質問があります。
if文で可変的にWhere句を付与して、SQLを実行させようとしています。その際ページングでページ遷移をすると、Where句の条件が抜けて全件検索になってしまい、どのような処理をすればWhere句を引き継げるのか困っている状態です。
もし、よろしければ、お知恵をお貸ししていただけないでしょうか。
よろしくお願いいたします。
WHERE句とページングの処理は直接関係していないので、WHERE句に関わる処理のどこかがおかしいのかと思います。
ソースコードを貼ってもらえれば何かしらコメント出来ると思います。
はじめまして!検索でこちらのサイトに辿り着いたのですが、まるで発注して作ってもらったかのような、まさに求めていたサンプルコード(省略タイプのページングをaJaxで実装したかったのです)で、ほんとに助かりました。
しかもクラスが苦手でどうしようかと思ったのですが、とても噛み砕いてわかりやすい説明をしてくださってたので概要も掴むことが出来ました。
お陰様で望んだものを実装することが出来ました。心より感謝いたします。ありがとうございました。