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で回し、リスト化します。

参考 PHPの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