解説コードを読んでみよう
このサンプルでわかること
- PHP の配列を
foreachで回して、表(HTML)を作る方法 json_encode()で PHP の配列を JSON に変え、JavaScript に渡す方法- 受け取ったデータを、ページを読み直さずにブラウザで並べ替え・絞り込みする方法
使っているファイル
- index.phpデモのページ
- data.php見本のデータ(果物の一覧)と、エスケープ用の関数
h()
1. データを用意する
果物の番号・品名・値段・在庫を、PHP の配列にまとめています。1件が「名前 => 値」の配列で、それが6件並んだ「配列の配列」です。
<?php
// 見本のデータ(果物の一覧)
// 本物のサービスでは、ここでデータベースから取り出します(解説の最後を参照)
function get_items(): array
{
return [
['id' => 1, 'name' => 'りんご', 'price' => 150, 'stock' => 12],
['id' => 2, 'name' => 'みかん', 'price' => 80, 'stock' => 30],
['id' => 3, 'name' => 'ぶどう', 'price' => 420, 'stock' => 5],
['id' => 4, 'name' => 'もも', 'price' => 300, 'stock' => 0],
['id' => 5, 'name' => 'バナナ', 'price' => 120, 'stock' => 18],
['id' => 6, 'name' => 'メロン', 'price' => 980, 'stock' => 2],
];
}
// 画面に出す文字をエスケープする(HTML のタグとして動かないようにする)
function h($s): string
{
return htmlspecialchars((string)$s, ENT_QUOTES, 'UTF-8');
}
2. PHP で表を作る(①)
ページの先頭で get_items() を呼んで $items に入れ、foreach で1件ずつ <tr> を作ります。値は必ず h() を通して画面に出します。
<h2>① PHP で表を作って表示する</h2>
<table class="table fruit-table">
<tr><th>番号</th><th>品名</th><th>値段</th><th>在庫</th></tr>
<?php foreach ($items as $item): ?>
<tr>
<td><?= h($item['id']) ?></td>
<td><?= h($item['name']) ?></td>
<td><?= h($item['price']) ?>円</td>
<td><?= $item['stock'] > 0 ? h($item['stock']) . '個' : '売り切れ' ?></td>
</tr>
<?php endforeach; ?>
</table>
この方法では、表はサーバーの中で作られてからブラウザに届きます。並べ替えたいときは、ページをもう一度読み込む必要があります。
3. JSON にして JavaScript に渡す(②)
json_encode() は、PHP の配列を JavaScript でそのまま読める形(JSON)の文字列に変えます。それを <script> の中に書き出せば、JavaScript の変数 items にデータが入ります。
// PHP の配列を JSON に変えて、JavaScript の変数に入れる
var items = <?= json_encode($items, JSON_UNESCAPED_UNICODE | JSON_HEX_TAG | JSON_HEX_AMP | JSON_HEX_APOS | JSON_HEX_QUOT) ?>;
| 付けているオプション | 働き |
|---|---|
JSON_UNESCAPED_UNICODE | 日本語を \u308a のような記号にせず、そのまま書き出す |
JSON_HEX_TAG など | < > & ' " を安全な書き方に変える。データに </script> が入っていても、ページが壊れたり、プログラムが動いたりしない |
4. ブラウザで並べ替える
データはもうブラウザにあるので、ボタンを押したときはサーバーに問い合わせず、JavaScript だけで並べ替え・絞り込みをします。
$(function(){
var sortKey = "id"; // 何の順に並べるか
function show() {
var list = items.slice(); // 元の配列をコピーしてから使う
if ($("#only-stock").prop("checked")) {
list = list.filter(function(item){ return item.stock > 0; });
}
list.sort(function(a, b){ return a[sortKey] - b[sortKey]; });
$("#list").empty();
$.each(list, function(i, item){
$("<li>").text(item.name + " " + item.price + "円").appendTo("#list");
});
}
$("button[data-sort]").on("click", function(){
sortKey = $(this).data("sort");
show();
});
$("#only-stock").on("change", show);
$("#raw").text(JSON.stringify(items, null, 1));
show();
});
画面に出すときは .text() を使っています。.html() と違い、文字をタグとして読まないので、データにタグが入っていても安全です。
どちらを使えばよいか
| ① PHP で表を作る | ② JSON で渡す | |
|---|---|---|
| 表を作る場所 | サーバー | ブラウザ |
| 向いていること | 検索エンジンに読ませたい一覧、ずっと同じ表示 | 並べ替え・絞り込み・グラフなど、その場で表示を変える画面 |
データベースを使うときは
このページは見本なので、データベースを使わずに動かしています。本物のサービスにするときは、データを取り出す関数の中身だけをデータベースの読み書きに取り替えます。画面の作り方(HTML と JavaScript)は同じままで使えます。
例えば get_items() の中を、次のように書き換えます(テーブル fruits を作り、接続の情報は公開フォルダの外の設定ファイルに置きます)。
function get_items(): array
{
$pdo = new PDO('mysql:host=localhost;dbname=sample;charset=utf8mb4', DB_USER, DB_PASS, [
PDO::ATTR_ERRMODE => PDO::ERRMODE_EXCEPTION,
]);
$stmt = $pdo->query('SELECT id, name, price, stock FROM fruits ORDER BY id');
return $stmt->fetchAll(PDO::FETCH_ASSOC);
}