ページング(ページの切り替え)

(ブログ記事の一覧は「こちら」)

Googleなど検索サイトで何かを検索した場合、大量の検索結果が得られますが、全てを表示しようとすると膨大な量になってしまうことがあるため、表示する項目を10個単位などに分割して、最下部に「1 2 3 4 5 6 7 8 9 10 次へ」のようなページのリンクを用意して、次の検索結果を選択する仕組みになっています。このような仕組みをページングと呼びます。

f:id:MJeeeey:20191103143006p:plain

ページングの考え方を用いて、表示を分割する方法を学びましょう。

ここで学ぶこと

  • ページング

準備

PHPからデータベースを操作(データの表示、検索)で用意したデータベースを使用します。

まず、ページングの動作を確認するため、データベースにレコードを120個追加するプログラムを用意します。PHPからデータベースを操作(データの挿入、更新、削除)で説明した、レコード追加を行うプログラム「insertFood_receive_pdo.php」を以下のように修正します。

<?php
    require_once('./dbConfig.php');

    $name = $_GET['name'];
    if (isset($name) == false) {
        die("'name'の設定なし");
    }

    $price = $_GET['price'];
    if (isset($price) == false) {
        die("'price'の設定なし");
    }

    $num = $_GET['num'];
    if (isset($num) == false) {
        die("'num'の設定なし");
    }

    // 接続
    try {
        $dsn = 'mysql:host=' . DB_SERVER . ';dbname=' . DB_NAME . ';charset=utf8';
        $pdo = new PDO($dsn, DB_USER, DB_PASS);
    } catch (PDOException $e) {
        exit("接続に失敗しました" . $e->getMessage());
    }

    // レコード追加
    $sql = "INSERT INTO fruits_list (id, name, price) VALUES (null, :name, :price)";
    if ($stmt = $pdo->prepare($sql)) {
        for($i = 1; $i <= $num; $i++) {
            $name_mod = $name . strval($i);
            $stmt->bindValue(':name', $name_mod, PDO::PARAM_STR);
            $price_mod = $price + $i;
            $stmt->bindValue(':price', $price_mod, PDO::PARAM_INT);
            $stmt->execute();
        }
    }

    $pdo = null;

    echo $name . "を" . $price . "円で追加しました。";
?>

以下を実行すると、レコードが120個追加されます。

http://localhost/sample/food/insertFood_receive_pdo.php?name=メロン&price=1000&num=120

復習

PHPからデータベースを操作(データの表示、検索)で説明した、全てのレコードの抽出を行うプログラム「getFoodName_receive_pdo.php」を再度以下に載せておきます。
こちらのサンプルプログラムをもとに、ページングを取り入れた表示に変更します。

<?php
    require_once('./dbConfig.php');

    // 接続
    try {
        $dsn = 'mysql:host=' . DB_SERVER . ';dbname=' . DB_NAME . ';charset=utf8';
        $pdo = new PDO($dsn, DB_USER, DB_PASS);
    } catch (PDOException $e) {
        die("接続に失敗しました" . $e->getMessage());
    }

    // レコード抽出
    $sql = "SELECT * FROM fruits_list";
    $stmt = $pdo->query($sql);

    echo "<ul>";
    foreach($stmt as $row) {
        echo "<li>" . $row['name'] . "</li>";
    }
    echo "</ul>";

    $pdo = null;
?>

例題

PHPからデータベースを操作(データの表示、検索)で作成したデータベースとPHPプログラムを使用して、ページングの仕組みになるようにPHPプログラムを修正します。

作成するもの

たくさんのレコード(データベースのデータのこと。できれば100個以上)を持つデータベースに対して、10個単位でデータを表示する、ページングの仕組みを作成します。

プログラム

上の復習のプログラムを参考に、以下のプログラムを「getFoodName_receive_pdo_paging.php」として作成してください。

<?php
    require_once('./dbConfig.php');

    $page = $_GET['page'];
    if (isset($page) == false) {
        $page = 0;
    }

    // 接続
    try {
        $dsn = 'mysql:host=' . DB_SERVER . ';dbname=' . DB_NAME . ';charset=utf8';
        $pdo = new PDO($dsn, DB_USER, DB_PASS);
    } catch (PDOException $e) {
        die("接続に失敗しました" . $e->getMessage());
    }

    $start = $page * 10;

    // 総件数カウント用
    $sql_cnt = "SELECT COUNT(*) FROM fruits_list";
    $stmt_cnt = $pdo->prepare($sql_cnt);
    $stmt_cnt->execute();
    $total = $stmt_cnt->fetchColumn();

    // データ抽出用
    $sql = "SELECT * FROM fruits_list ORDER BY id LIMIT :start, 10";
    $stmt = $pdo->prepare($sql);
    $stmt->bindValue(":start", $start, PDO::PARAM_INT);
    $stmt->execute();
    $data = $stmt->fetchAll(PDO::FETCH_ASSOC);

    // 総件数
    echo "全 " . $total . " 件<br>";
    // 抽出箇所
    echo $start . " 件目~ " . ($start + count($data)) .  " 件目<br>";
    // 総ページ数(総件数 / 1ページに表示する件数 を切り上げたもの)
    $pages = ceil($total / 10);
    echo "総ページ数 " . $pages . "<br>";

    // 抽出したページのデータを表示
    echo "<ul>";
    foreach ($data as $row) {
        echo "<li>" . $row['name'] . " " . $row['price'] . "</li>";
    }
    echo "</ul>";

    // ページのリンク
    for ($i = 0; $i < $pages; $i++) {
        if ($i == $page) {
            // 自身のページなので、リンクを追加しない
            printf("%d ", $i + 1);
        } else {
            printf("<a href='?page=%d'>%d</a> ", $i, $i + 1);
        }
    }

    $pdo = null;
?>

まず、$_GET['page'] を呼び出し、指定したページの番号を取得します。
実行するSQL文は、総件数カウント用とデータ抽出用の2つが必要になります。取得した総件数をもとに、最下部にページのリンクを追加します。

実行、確認

以下のURLを実行します。

http://localhost/sample/food/getFoodName_receive_pdo_paging.php?page=0

10個単位でデータを表示する、ページングの仕組みができていることを確認してください。

課題ではありませんが、表示する項目を10個単位から20個単位に変更するにはどうするか、についても考えてみましょう。

課題1

例題のプログラムをもとに、ページに「前へ」「次へ」ボタンを追加してください。

課題2

例題のプログラムをもとに、「name」(名前)に対して、指定したキーワードを検索する機能を追加してください。
以下のURLを実行して、検索結果が得られるように、例題のプログラムを修正してください。

http://localhost/sample/food/getFoodName_receive_pdo_paging.php?page=0&q=みかん