「テーブルを作成する」で作ったデータベースの一覧を表示してみたいと思います。
「PHPからデータベースに接続する」で作ったファイル「list.php」に書き足していきたいと思います。
データベースは接続しただけではデータの保存・参照といった操作ができるわけではありません。SQL文を使ってデータベースに命令を送る必要があります。そのデータベースの基本的な操作を使って一覧表を作っていきます。
まずは実行するSQL分を準備します。
$sql = "SELECT * FROM fruits";
テーブル「fruits
」の全ての内容「*
(アスタリスク)」を抜き出すためのSQL文「SELECT * FROM fruits
」を用意して、その実行結果を次の行で使えるように変数「$sql
」に代入しています。これで SQL文を実行する準備ができました。
ここまでの全文
<?php
try {
// データベースへ接続する
$handle = new PDO('sqlite:Sample.db');
// PDO実行時のエラーモードを設定する
$handle->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);
// SQL文の準備
$sql = "SELECT * FROM fruits";
// データベースとの接続を終了する
$handle = null;
} catch (PDOException $e) {
// エラー内容を表示する
echo "エラー発生:" . htmlspecialchars($e->getMessage(), ENT_QUOTES, 'UTF-8') . "<br>";
// 全ての命令を中止する
die();
}
?>
次にSQL文を実行して結果を問い合わせします。
$stmt = $handle->query($sql);
PDOでデータベースに接続「$handle
」して準備した SQL文を実行します。そしてその結果が格納された変数「$sql
」の内容を問い合わせ「query
」して、結果を変数「$stmt
」に格納します。queryとは「質問する」、「問い合わせる」といった意味です。
ここまでの全文
<?php
try {
// データベースへ接続する
$handle = new PDO('sqlite:Sample.db');
// PDO実行時のエラーモードを設定する
$handle->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);
// SQL文の準備
$sql = "SELECT * FROM fruits";
// SQL文の実行
$stmt = $handle->query($sql);
// データベースとの接続を終了する
$handle = null;
} catch (PDOException $e) {
// エラー内容を表示する
echo "エラー発生:" . htmlspecialchars($e->getMessage(), ENT_QUOTES, 'UTF-8') . "<br>";
// 全ての命令を中止する
die();
}
?>
次はSQL文の結果を配列として取り出します。
$result = $stmt->fetchAll(PDO::FETCH_ASSOC);
SQL文の実行結果「$stmt
」をField名を付けた配列として取り出して変数「$result
」に格納します。配列として全て取り出す命令は fetchAll()
という関数です。この引数に PDO::FETCH_ASSOC
という部分があります。これは、
これら3つから選んで使います。FETCH_ASSOCはField名を付けた配列として返すので、プログラムを作成する上で見通しが良くなります。FETCH_NUMは 0 から始まるField番号を付けて返すため、結果を順番に処理する場合(ループ処理など)に使います。FETCH_BOTHはField名とField番号を付けて返すため配列自体が見にくくなってしまいます。結果的に利用する機会は少ないようです。
ここまでの全文
<?php
try {
// データベースへ接続する
$handle = new PDO('sqlite:Sample.db');
// PDO実行時のエラーモードを設定する
$handle->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);
// SQL文の準備
$sql = "SELECT * FROM fruits";
// SQL文の実行
$stmt = $handle->query($sql);
// SQL文の結果の取り出し
$result = $stmt->fetchAll(PDO::FETCH_ASSOC);
// データベースとの接続を終了する
$handle = null;
} catch (PDOException $e) {
// エラー内容を表示する
echo "エラー発生:" . htmlspecialchars($e->getMessage(), ENT_QUOTES, 'UTF-8') . "<br>";
// 全ての命令を中止する
die();
}
?>
最後に取り出した結果を書き出します。
print_r($result);
配列として取り出した結果「$result
」を print_r()
関数で出力します。
ここまでの全文
<?php
try {
// データベースへ接続する
$handle = new PDO('sqlite:Sample.db');
// PDO実行時のエラーモードを設定する
$handle->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);
// SQL文の準備
$sql = "SELECT * FROM fruits";
// SQL文の実行
$stmt = $handle->query($sql);
// SQL文の結果の取り出し
$result = $stmt->fetchAll(PDO::FETCH_ASSOC);
// 結果を書き出す
print_r($result);
// データベースとの接続を終了する
$handle = null;
} catch (PDOException $e) {
// エラー内容を表示する
echo "エラー発生:" . htmlspecialchars($e->getMessage(), ENT_QUOTES, 'UTF-8') . "<br>";
// 全ての命令を中止する
die();
}
?>
ここまで完成したファイルを「RUN」で実行してみます。
画面に、
Array ( [0] => Array ( [id] => 1 [name] => バナナ [price] => 181 ) [1] => Array ( [id] => 2 [name] => みかん [price] => 433 ) [2] => Array ( [id] => 3 [name] => りんご [price] => 373 ) )
といった感じでずらずらっと表示されていれば成功です。
そして、わざとテーブルの名前を間違えて入力してみました。これを実行してみます。
スペルミスのあるコード
<?php
try {
// データベースへ接続する
$handle = new PDO('sqlite:Sample.db');
// PDO実行時のエラーモードを設定する
$handle->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);
// SQL文の準備
$sql = "SELECT * FROM friuts";
// SQL文の実行
$stmt = $handle->query($sql);
// SQL文の結果の取り出し
$result = $stmt->fetchAll(PDO::FETCH_ASSOC);
// 結果を書き出す
print_r($result);
// データベースとの接続を終了する
$handle = null;
} catch (PDOException $e) {
// エラー内容を表示する
echo "エラー発生:" . htmlspecialchars($e->getMessage(), ENT_QUOTES, 'UTF-8') . "<br>";
// 全ての命令を中止する
die();
}
?>
「エラー発生:SQLSTATE[HY000]: General error: 1 no such table: friuts」要約すると「friuts というテーブルはありません」とエラーメッセージも正しく表示されましたので成功です。
続いて、一覧表にするために見出し行を作っていきます。
先ほど結果を書き出すために使った「print_r($result);
」はデータベースの中身を確認するためのものなので、もう必要ありませんから削除します。
その代わりに表を作成するためのタグ「<table>〜</table>
」を入力します。でも、PHPモードの中なので直接タグを入力しても意味がありません。そこで、echo
で <table>
タグの表示を指示します。
さらにそれぞれの表示に \n
を追加して改行の指示をしておきます。
echo "<table>\n";
echo "<tr>\n";
echo "<th>ID</th><th>名前</th><th>価格</th>\n";
echo "</tr>\n";
echo "</table>\n";
\n
で改行の指示をしておくとブラウザでソースを見たときにタグが改行されて表示されます。
\n
で改行の指示がない場合は、タグが横に並んで見づらくなってしまいます。
メンテナンスの際などにソースを確認する場合、改行してあった方が見やすくなりますので忘れずに\n
で改行の指示を入れておいた方が良さそうです。
ここまでの全文
<?php
try {
// データベースへ接続する
$handle = new PDO('sqlite:Sample.db');
// PDO実行時のエラーモードを設定する
$handle->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);
// SQL文の準備
$sql = "SELECT * FROM fruits";
// SQL文の実行
$stmt = $handle->query($sql);
// SQL文の結果の取り出し
$result = $stmt->fetchAll(PDO::FETCH_ASSOC);
// 結果を書き出す
print_r($result); // 不要になったので削除
// テーブルを作る
echo "<table>\n";
echo "<tr>\n";
echo "<th>ID</th><th>名前</th><th>価格</th>\n";
echo "</tr>\n";
echo "</table>\n";
// データベースとの接続を終了する
$handle = null;
} catch (PDOException $e) {
// エラー内容を表示する
echo "エラー発生:" . htmlspecialchars($e->getMessage(), ENT_QUOTES, 'UTF-8') . "<br>";
// 全ての命令を中止する
die();
}
?>
ここまでに出来た「list.php」を実行してみます。表のタイトル行が表示されていれば成功です。
続いて、繰り返し処理でデータベースの中身を並べて表を作成します。
foreach ($result as $row) {
echo "<tr>\n";
echo "<td></td>\n";
echo "<td></td>\n";
echo "<td></td>\n";
echo "</tr>\n";
}
プログラミングでは、繰り返し処理のことをループと呼びます。繰り返し処理を行うための命令はいくつかありますが、ここでは foreach()
という構文を利用します。
foreach (配列 as 変数) {処理}
ここでの配列はデータベースから取り出した $result
を指定します。$result
には指定したテーブルのデータがずらりと並んでいる状態です。as
の後の変数にループ中に利用する変数を指定します。変数名は $row
としています。これで $result
の内容が上から順に1行ずつ、繰り返し $row
に代入されるようになります。つまり、データベースに「バナナ」「みかん」「りんご」の3つのデータが順番に登録されていますので、最初の $row
には「バナナ」のデータ、2巡目には「みかん」、3巡目に「りんご」のデータが代入されるようになります。全て巡回したら自動的に停止します。後は1行ずつ取り出されたデータを表として表示するように処理部分を作っていきます。
foreach ($result as $row) {
echo "<tr>\n";
echo "<td>".$row['id']."</td>\n";
echo "<td>".$row['name']."</td>\n";
echo "<td>".$row['price']."</td>\n";
echo "</tr>\n";
}
それぞれの列の中身を作っていきます。1列目にID、2列目に名前、3列目に価格を入れます。ここで先ほど指定した $row
が登場します。この $row
にはテーブルのデータが1行ずつ入っていますので、ID、名前、価格の全てのデータが入っています。それぞれ3つの列のキーを指定して <td>〜</td>
の間に入力します。この時に文字列を連結する .
(ピリオド)で区切るのを忘れないようにして下さい。
$row['name']
$row
には、1行分すべてのデータが入っています。まだ、大きな箱の中にいろいろな値が小さな箱に入っている状態です。その中で、特定の値を取り出すラベルのようなものを「キー」と呼んでいます。名前であれば 'name'
がキーになります。
ここまでの全文
<?php
try {
// データベースへ接続する
$handle = new PDO('sqlite:Sample.db');
// PDO実行時のエラーモードを設定する
$handle->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);
// SQL文の準備
$sql = "SELECT * FROM fruits";
// SQL文の実行
$stmt = $handle->query($sql);
// SQL文の結果の取り出し
$result = $stmt->fetchAll(PDO::FETCH_ASSOC);
// テーブルを作る
echo "<table>\n";
echo "<tr>\n";
echo "<th>ID</th><th>名前</th><th>価格</th>\n";
echo "</tr>\n";
foreach ($result as $row) {
echo "<tr>\n";
echo "<td>".$row['id']."</td> \n";
echo "<td>".$row['name']."</td>\n";
echo "<td>".$row['price']."</td>\n";
echo "</tr>\n";
}
echo "</table>\n";
// データベースとの接続を終了する
$handle = null;
} catch (PDOException $e) {
// エラー内容を表示する
echo "エラー発生:" . htmlspecialchars($e->getMessage(), ENT_QUOTES, 'UTF-8') . "<br>";
// 全ての命令を中止する
die();
}
?>
このままでもテストするだけであれば一応実行は可能ですが、プログラムを公開することを考えて念のためにセキュリティ対策をします。echo
で表示するのは本来は誰かが入力フォームからデータベースに登録した値です。そのため、悪意を持ったユーザーに、悪さをするプログラムを仕込まれた値が入力されてしまうと、途端に正しく動作しなくなる可能性があります。そこで htmlspecialchars
関数を設定します。3つの列それぞれにhtmlspecialchars
の設定を追加します。
ここまでの全文
<?php
try {
// データベースへ接続する
$handle = new PDO('sqlite:Sample.db');
// PDO実行時のエラーモードを設定する
$handle->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);
// SQL文の準備
$sql = "SELECT * FROM fruits";
// SQL文の実行
$stmt = $handle->query($sql);
// SQL文の結果の取り出し
$result = $stmt->fetchAll(PDO::FETCH_ASSOC);
// テーブルを作る
echo "<table>\n";
echo "<tr>\n";
echo "<th>ID</th><th>名前</th><th>価格</th>\n";
echo "</tr>\n";
foreach ($result as $row) {
echo "<tr>\n";
echo "<td>".htmlspecialchars($row['id'], ENT_QUOTES, 'UTF-8')."</td> \n";
echo "<td>".htmlspecialchars($row['name'], ENT_QUOTES, 'UTF-8')."</td>\n";
echo "<td>".htmlspecialchars($row['price'], ENT_QUOTES, 'UTF-8')."</td>\n";
echo "</tr>\n";
}
echo "</table>\n";
// データベースとの接続を終了する
$handle = null;
} catch (PDOException $e) {
// エラー内容を表示する
echo "エラー発生:" . htmlspecialchars($e->getMessage(), ENT_QUOTES, 'UTF-8') . "<br>";
// 全ての命令を中止する
die();
}
?>
データベースに登録したすべての果物が一覧表として表示されれば成功です。