1
3

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 3 years have passed since last update.

PHPにおけるページネーションの方法

Last updated at Posted at 2020-07-27

初投稿です。
PHPのページネーションに関して、以前実装したものの知識が抜けていたので、アウトプットがてら復習したいと思います。何かのお役に立てれば幸いです。

要件
・各ページで5つずつ表示する
・ページの前後には「前へ」「次へ」を表示。複数ページある場合はリンクになり、それぞれのボタンを押すと前後のページへジャンプする
・ページ番号は5つまで表示。基本的に現在表示されているページの前後2つを表示させる
・ページ数が表示されてる部分にあわせて「○件中○〜○件目の商品」と記載する

なお、今回はLaravelなどのフレームワークは使わずに、生のPHPで実装します。

イメージとしてはこんな感じです。

スクリーンショット 2020-07-27 22.36.07.png

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でもページネーションを実装してみたいな。

1
3
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
1
3

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?