著者は、Write for DOnationsプログラムの一部として寄付を受け取るためにthe Apache Software Foundationを選択しました。
前書き
ページネーションは、レコードセットで返される行の数を別々の整然としたページに制限して、それらの間のナビゲーションを容易にする概念です。そのため、大きなデータセットがある場合、各ページで特定の行数のみを返すようにページネーションを設定できます。 たとえば、ページにリストされるアイテムの数を減らすことで、ウェブストアに何千もの製品が含まれる場合、ユーザーがすべての製品を表示する必要はほとんどないため、ページネーションは圧倒的なユーザーの回避に役立ちます。 別の例は、モバイルデバイスでレコードを表示するアプリケーションです。このような場合にページネーションを有効にすると、レコードが複数のページに分割され、画面に収まりやすくなります。
エンドユーザーにとっての視覚的な利点に加えて、ページネーションは、一度に返されるレコードの数を減らすため、アプリケーションを高速化します。 これにより、クライアントとサーバー間で送信する必要のあるデータが制限され、RAMなどのサーバーリソースの保持に役立ちます。
このチュートリアルでは、データベースに接続するためのPHPスクリプトを作成し、MySQLLIMIT
clauseを使用してスクリプトへのページ付けを実装します。
前提条件
開始する前に、次のものが必要です。
-
sudo非rootユーザーを含むInitial Server Setup with Ubuntu 18.04をフォローしてセットアップされた1つのUbuntu18.04サーバー。
-
システムにインストールされているApache、MySQL、およびPHP。 How To Install Linux, Apache, MySQL, PHP (LAMP) stack on Ubuntu 18.04のガイドに従うことができます。
[[step-1 -—- creating-a-database-user-and-a-test-database]] ==ステップ1—データベースユーザーとテストデータベースの作成
このチュートリアルでは、MySQLデータベースに接続してレコードを取得し、テーブル内のHTMLページに表示するPHPスクリプトを作成します。 Webブラウザから2つの異なる方法でPHPスクリプトをテストします。 最初に、ページネーションコードなしでスクリプトを作成して、レコードの表示方法を確認します。 次に、ページ編集コードをPHPファイルに追加して、ページネーションが実際にどのように機能するかを理解します。
PHPコードには、認証目的のMySQLユーザーと接続するサンプルデータベースが必要です。 この手順では、PHPスクリプトをテストするために、MySQLデータベース、サンプルデータベース、およびテーブルの非ルートユーザーを作成します。
サーバーへのログインを開始します。 次に、次のコマンドを使用してMySQLサーバーにログインします。
sudo mysql -u root -p
MySQLサーバーのrootパスワードを入力し、ENTER
を押して続行します。 次に、MySQLプロンプトが表示されます。 このチュートリアルでtest_db
と呼ぶサンプルデータベースを作成するには、次のコマンドを実行します。
Create database test_db;
次の出力が表示されます。
OutputQuery OK, 1 row affected (0.00 sec)
次に、test_user
を作成し、ユーザーにtest_db
に対するすべての特権を付与します。 PASSWORD
を強い値に置き換えます。
GRANT ALL PRIVILEGES ON test_db.* TO 'test_user'@'localhost' IDENTIFIED BY 'PASSWORD';
OutputQuery OK, 1 row affected (0.00 sec)
次を使用してMySQL権限をリロードします。
FLUSH PRIVILEGES;
OutputQuery OK, 1 row affected (0.00 sec)
次に、test_db
データベースに切り替えて、test_db
データベースで直接作業を開始します。
Use test_db;
OutputDatabase changed
次に、products
テーブルを作成します。 表にはサンプル製品が含まれます。このチュートリアルでは、データ用に2列のみが必要です。 product_id
列は、各レコードを一意に識別するための主キーとして機能します。 product_name
フィールドを使用して、各アイテムを名前で区別します。
Create table products (product_id BIGINT PRIMARY KEY, product_name VARCHAR(50) NOT NULL ) Engine = InnoDB;
OutputQuery OK, 0 rows affected (0.02 sec)
10個のテスト製品をproducts
テーブルに追加するには、次のSQLステートメントを実行します。
Insert into products(product_id, product_name) values ('1', 'WIRELESS MOUSE');
Insert into products(product_id, product_name) values ('2', 'BLUETOOTH SPEAKER');
Insert into products(product_id, product_name) values ('3', 'GAMING KEYBOARD');
Insert into products(product_id, product_name) values ('4', '320GB FAST SSD');
Insert into products(product_id, product_name) values ('5', '17 INCHES TFT');
Insert into products(product_id, product_name) values ('6', 'SPECIAL HEADPHONES');
Insert into products(product_id, product_name) values ('7', 'HD GRAPHIC CARD');
Insert into products(product_id, product_name) values ('8', '80MM THERMAL PRINTER');
Insert into products(product_id, product_name) values ('9', 'HDMI TO VGA CONVERTER');
Insert into products(product_id, product_name) values ('10', 'FINGERPRINT SCANNER');
次の出力が表示されます。
OutputQuery OK, 1 row affected (0.02 sec)
以下を実行して、製品がテーブルに挿入されたことを確認します。
select * from products;
出力の製品は2つの列内に表示されます。
Output+------------+-----------------------+
| product_id | product_name |
+------------+-----------------------+
| 1 | WIRELESS MOUSE |
| 2 | BLUETOOTH SPEAKER |
| 3 | GAMING KEYBOARD |
| 4 | 320GB FAST SSD |
| 5 | 17 INCHES TFT |
| 6 | SPECIAL HEADPHONES |
| 7 | HD GRAPHIC CARD |
| 8 | 80MM THERMAL PRINTER |
| 9 | HDMI TO VGA CONVERTER |
| 10 | FINGERPRINT SCANNER |
+------------+-----------------------+
10 rows in set (0.00 sec)
MySQLを終了します。
quit;
サンプルデータベース、テーブル、およびテストデータを配置したら、Webページにデータを表示するPHPスクリプトを作成できます。
[[step-2 -—- displaying-mysql-records-without-pagination]] ==ステップ2—ページネーションなしでMySQLレコードを表示する
次に、前の手順で作成したMySQLデータベースに接続するPHPスクリプトを作成し、Webブラウザーで製品を一覧表示します。 このステップでは、ページ分割の形式を使用せずにPHPコードを実行して、非分割レコードが単一ページにどのように表示されるかを示します。 このチュートリアルではテスト目的のレコードは10個しかありませんが、ページネーションなしのレコードを見ると、データをセグメント化することで最終的にユーザーエクスペリエンスが向上し、サーバーの負荷が軽減される理由がわかります。
次のコマンドを使用して、WebサイトのドキュメントルートにPHPスクリプトファイルを作成します。
sudo nano /var/www/html/pagination_test.php
次に、次のコンテンツをファイルに追加します。 PASSWORD
を、前の手順でtest_user
に割り当てた正しいパスワードの値に置き換えることを忘れないでください。
/var/www/html/pagination_test.php
setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);
$pdo->setAttribute(PDO::ATTR_EMULATE_PREPARES,false);
$sql="select * from products";
$stmt = $pdo->prepare($sql);
$stmt->execute();
echo "";
while ( ($row = $stmt->fetch(PDO::FETCH_ASSOC) ) !== false) {
echo "";
echo "".$row['product_id']." ";
echo "".$row['product_name']." ";
echo " ";
}
echo "
";
}
catch(PDOException $e)
{
echo $e->getMessage();
}
?>
CTRL+X
、Y
、およびENTER
を押してファイルを保存します。
このスクリプトでは、ステップ1で作成したデータベース資格情報を使用してPDO (PHP Data Object)ライブラリを使用してMySQLデータベースに接続しています。
PDOは、データベースに接続するための軽量のインターフェイスです。 データアクセス層はより移植性が高く、わずかなコードの書き換えだけで異なるデータベースで動作できます。 PDOは、prepared statementsをサポートしているため、セキュリティが強化されています。これは、クエリを安全な方法で高速に実行するための機能です。
次に、select * from products
ステートメントを実行し、ページ付けなしでHTMLテーブルに製品を一覧表示するようにPDOAPIに指示します。 行$pdo->setAttribute(PDO::ATTR_EMULATE_PREPARES,false);
は、データ型がデータベースに表示されるとおりに返されることを保証します。 これは、PDOがproduct_id
を整数として返し、product_name
を文字列として返すことを意味します。 $pdo->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);
は、エラーが発生した場合に例外をスローするようにPDOに指示します。 デバッグを容易にするために、PHPtry{}...catch{}
ブロック内のエラーをキャッチしています。
作成した/var/www/html/pagination_test.php
PHPスクリプトファイルを実行するには、次のURLにアクセスして、your-server-IP
をサーバーのパブリックIPアドレスに置き換えます。
http://your-server-IP/pagination_test.php
製品の表を含むページが表示されます。
PHPスクリプトは期待どおりに機能しています。すべての製品を1ページにリストします。 数千の製品がある場合、製品がデータベースからフェッチされ、PHPページにレンダリングされるため、これにより長いループが発生します。
この制限を克服するには、PHPスクリプトを変更し、MySQLLIMIT
句といくつかのナビゲーションリンクを表の下部に含めて、ページ付け機能を追加します。
[[step-3 -—- implementing-pagination-with-php]] ==ステップ3—PHPを使用したページネーションの実装
このステップの目標は、テストデータを複数の管理可能なページに分割することです。 これにより、読みやすくなるだけでなく、サーバーのリソースをより効率的に使用できます。 前のステップで作成したPHPスクリプトを変更して、ページネーションに対応します。
これを行うには、MySQLLIMIT
句を実装します。 これをスクリプトに追加する前に、MySQLLIMIT
の構文の例を見てみましょう。
Select [column1, column2, column n...] from [table name] LIMIT offset, records;
LIMIT
句は、このステートメントの終わりに向かって示されているように、2つの引数を取ります。 offset
値は、最初の行の前にスキップするレコードの数です。 records
は、ページごとに表示するレコードの最大数を設定します。
ページネーションをテストするには、ページごとに3つのレコードを表示します。 ページの合計数を取得するには、テーブルの合計レコードをページごとに表示する行で分割する必要があります。 次に、次のPHPコードスニペットの例に示すように、PHPCeil
関数を使用して、結果の値を最も近い整数に丸めます。
$total_pages=ceil($total_records/$per_page);
以下は、完全なページネーションコードを使用したPHPスクリプトの修正バージョンです。 ページネーションコードとナビゲーションコードを含めるには、/var/www/html/pagination_test.php
ファイルを開きます。
sudo nano /var/www/html/pagination_test.php
次に、強調表示された次のコードをファイルに追加します。
/var/www/html/pagination_test.php
setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);
$pdo->setAttribute(PDO::ATTR_EMULATE_PREPARES,false);
/* Begin Paging Info */
$page=1;
if (isset($_GET['page'])) {
$page=filter_var($_GET['page'], FILTER_SANITIZE_NUMBER_INT);
}
$per_page=3;
$sqlcount="select count(*) as total_records from products";
$stmt = $pdo->prepare($sqlcount);
$stmt->execute();
$row = $stmt->fetch();
$total_records= $row['total_records'];
$total_pages=ceil($total_records/$per_page);
$offset=($page-1)*$per_page;
/* End Paging Info */
$sql="select * from products limit $offset,$per_page";
$stmt = $pdo->prepare($sql);
$stmt->execute();
echo "";
while ( ($row = $stmt->fetch(PDO::FETCH_ASSOC) ) !== false) {
echo "";
echo "".$row['product_id']." ";
echo "".$row['product_name']." ";
echo " ";
}
echo "
";
/* Begin Navigation */
echo "";
echo "";
if( $page-1>=1) {
echo "Previous ";
}
if( $page+1<=$total_pages) {
echo "Next ";
}
echo " ";
echo "
";
/* End Navigation */
}
catch(PDOException $e) {
echo $e->getMessage();
}
?>
ファイルでは、追加のパラメーターを使用してページングを実行しました。
-
$page
:この変数は、スクリプトの現在のページを保持します。 ページ間を移動するとき、スクリプトは$_GET['page']
変数を使用してpage
という名前のURLパラメーターを取得します。 -
$per_page
:この変数は、ページごとに表示する最大レコードを保持します。 あなたの場合、各ページに3つの製品をリストしたいと思います。 -
$total_records
:製品を一覧表示する前に、SQLステートメントを実行して、ターゲットテーブル内のレコードの総数を取得し、それを$total_records
変数に割り当てます。 -
$offset
:この変数は、最初の行の前にスキップするレコードの合計を表します。 この値は、式$offset=($page-1)*$per_page
を使用してPHPスクリプトによって動的に計算されます。 この式をPHPページネーションプロジェクトに適合させることができます。 必要に応じて$per_page
変数を変更できることを忘れないでください。 たとえば、モバイルデバイス用のウェブサイトまたは別の金額を実行している場合は、値を50
に変更して、ページごとに50個のアイテムを表示できます。
ここでも、ブラウザでIPアドレスにアクセスし、your_server_ip
をサーバーのパブリックIPアドレスに置き換えます。
http://your_server_ip/pagination_test.php
ページの下部にいくつかのナビゲーションボタンが表示されます。 最初のページでは、Previousボタンは表示されません。 Nextページボタンが表示されない最後のページでも同じケースが発生します。 また、各ページにアクセスすると、page
URLパラメーターがどのように変化するかに注意してください。
ページの下部にあるナビゲーションリンクは、ファイルから次のPHPコードスニペットを使用して実現されます。
/var/www/html/pagination_test.php
ここで、$page
変数は現在のページ番号を表します。 次に、前のページを取得するために、コードは変数から1
を引きます。 したがって、2ページ目にいる場合、数式(2-1)
は1
の結果を示し、これがリンクに表示される前のページになります。 ただし、1
以上の結果が得られた場合にのみ、前のページが表示されることに注意してください。
同様に、次のページに移動するには、$page
変数に1を追加し、page
URLパラメーターに追加する$page
の結果が以下であることを確認する必要があります。 PHPコードで計算した合計ページ数。
この時点で、PHPスクリプトはページネーションを処理しており、レコードナビゲーションを改善するためにMySQLLIMIT
句を実装できます。
結論
このチュートリアルでは、Ubuntu 18.04サーバー上のPHPでMySQLのページングを実装しました。 PHPスクリプトを使用してページネーションを含めることにより、これらの手順をより大きなレコードセットで使用できます。 Webサイトまたはアプリケーションでページネーションを使用することで、ユーザーナビゲーションを改善し、サーバーでリソースを最適に使用できます。
ここから、これらのチュートリアルを使用して、データベースおよびその他のデータベースタスクのさらなる最適化を検討できます。