VS CodeとPHPとPDO(PHP Data Objects)とSQL Serverを使って、簡単なToDoリストアプリを作ってみよう。
前回はSQL Server LocalDBを例に、PHPからSQL Serverに接続するために必要な手順を見た。ありがちな例だが、今回からはToDoリストアプリを作りながら、PHPが提供するPDO(PHP Data Objects)を使用して、SQL Serverからのデータの取得とデータの追加の手順を見てみよう。
なお、今回はWindows版のVisual Studio Code(以下、VS Code)にPHP IntelliSense拡張機能とPHP Debug拡張機能、PHP Server拡張機能などをインストールした環境で動作を確認している。これらの拡張機能については「PHPプログラミングも快適に! VS Codeの二大拡張機能」「VS CodeからPHPアプリをローカル実行/デプロイ!」「VS CodeとPHPとIISでアプリ開発:準備編」などを参考にしてほしい。
ここでは前回に作成したSQL Server LocalDBのvscphpwebappsインスタンス上にtodolistデータベースを作成し、そこにToDoリストを保存するtodoitemsテーブルを作成した。このテーブルでは以下のデータを保存する。
以下にテーブルのデザインと、そのデータを示す(データは実際にアプリの動作を検証しながら追加したもの)。
done列は今回は使用しないが、次回にデータを更新する際に利用する予定だ。
まずはデータベースに接続して、そこから上記に示したデータを取得するコードを見てみよう。vscphpwebapps_05ディレクトリを作成し、そこに以下に示すindex.phpファイルを作成した。
<?php
try {
$serverName = "(localDB)\\vscphpwebapps";
$uid = "sa";
$pwd = "**********";
$dbname = "todolist";
$dsn = "sqlsrv:server=" . $serverName . ";database=" . $dbname;
$pdo = new PDO($dsn, $uid, $pwd, [
PDO::ATTR_ERRMODE => PDO::ERRMODE_EXCEPTION
]);
//$pdo = new PDO($dsn, $uid, $pwd);
//$pdo->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);
$tsql = "SELECT * from todoitems";
$stmt = $pdo->query($tsql);
} catch (Exception $e) {
$stmt = null;
$pdo = null;
header("Content-Type: text/plain; charset=UTF-8", true, 500);
exit();
//exit($e->getMessage());
}
?>
<!DOCTYPE html>
<html lang="ja">
<head>
<meta charset="UTF-8">
<title>ToDo List</title>
</head>
<body>
<h1>To Do List</h1>
<ul>
<?php foreach ($stmt as $row) {?>
<li><?=htmlspecialchars($row["item"], ENT_QUOTES)?></li>
<?php }?>
<?php
$stmt = null;
$pdo = null;
?>
</ul>
<p>register todo item</p>
<form action="additem.php" method="post">
item:
<input name="item">
<input type="submit" name="submit">
</form>
</body>
</html>
上のファイルの冒頭部分では、try-catch構文を利用して、データベースへの接続とクエリの実行まで行っている(tryブロックで囲んだ範囲が広いような気がするが、サンプルだと思ってご容赦されたい)。PHPの例外処理は次の形式を取る。
<?php
try {
// 例外を発生させる可能性がある処理
} catch (Exception $e) {
// 例外処理
} finally {
// 例外の有無に関係なく最後に実行する処理
}
tryブロックで例外が発生する可能性のある処理を囲み、例外発生時の処理をcatchブロックに記述し、例外の有無に関係なく最後に行うべき処理をfinallyブロックに書くというのは、C#などの言語と同様だ。上のコードでは、手抜きをして、全ての例外の基底クラスとなっているExceptionクラスで例外を補足している。PHPの組み込み例外クラスについては、PHPのドキュメント「定義済みの例外」を参考にしてほしい。
tryブロックで行っている処理は前回に見たPDOインスタンスの生成、queryメソッドによるSQLの実行を踏襲している。前回と異なっているのは、PDOインスタンスの生成時にオプションを渡して、データベースハンドルのPDO::ATTR_ERRMODE属性の値をPDO::ERRMODE_EXCEPTIONに設定しているところだ。これは、データベース接続が失敗したときに例外が発生するようになる。上のコードではコンストラクタに渡しているが、その下のコメントアウトした行のようにsetAttributeメソッドを使い、インスタンス生成後に属性を設定することも可能だ。例外を発生させるようにすることで、try-catchによる例外処理が可能になる。
catchブロックでは(例外が発生したときには)、作成したPDOインスタンスと、そのインスタンスを利用して実行するクエリ($pdo->query(……))が返送するPDOStatementクラスのインスタンスを「$pdo = null;」のようにして削除している。例外が発生しなかった場合は、その下にあるHTMLに埋め込まれたPHPコード内で削除している。
PDO/PDOStatementインスタンスを削除した後には、PHPのheader関数を利用して、エラーが発生したことをユーザーに通知するようにしている。この関数は「生のHTTPヘッダを送信する」ための関数であり、ここでは必要最低限のヘッダ情報とレスポンスコード500(Internal Server Error)を送信するようにしている。例えば、上のコードでデータベース名やテーブル名を存在しないものにして(あるいは間違えたユーザー名やパスワードにして)実行すると、次のような画面が表示される(この実行画面は、VS CodeのPHP Server拡張機能を利用して、ローカルにホストしたもの。実は、そのままこのプロジェクトをIISに展開してもうまく実行できない。これについては次回以降で取り上げる予定だ)。
あるいは、catchブロックで補足したExceptionクラスのインスタンス($e)を使ってより詳細なエラーメッセージを表示させることも可能だ。上のコードでコメントアウトされている「exit($e->getMessage());」行を参考にされたい。
なお、header関数で「Location:」ヘッダを送信することで、特定のページにリダイレクトすることも可能だ(後で使ってみよう)。
取得したデータはHTMLの中で次のようにして、表示している。
<?php
try {
// …… 省略 ……
} catch (Exception $e) {
// …… 省略 ……
}
?>
<!DOCTYPE html>
<html lang="ja">
<head>
<!-- …… 省略 …… -->
</head>
<body>
<h1>To Do List</h1>
<ul>
<?php foreach ($stmt as $row) {?>
<li><?=htmlspecialchars($row["item"], ENT_QUOTES)?></li>
<?php }?>
<?php
$stmt = null;
$pdo = null;
?>
</ul>
<!-- …… 省略 …… -->
</body>
</html>
PDOでは取得したデータの反復処理が可能なため、上のコードではforeach文でループを回している。また、<li>要素内部ではhtmlspecialchars関数を使って、todoitemsテーブルに保存された内容(文字列)をHTMLエンティティにエスケープしている(第2引数のENT_QUOTESはシングルクオートとダブルクオートの両者を含めて特殊文字をHTMLエンティティに変換することを意味する)。その後は、使用した2つのリソースの削除をしているだけだ。
最後に省略しているところで、HTMLフォームを作成して、ToDoアイテムを登録できるようにしている。これについては次ページで触れる。
PHP Server拡張機能を使い、上のコードをローカルにホストした画面を示す。
次にデータを追加するコードを見てみよう。
Copyright© Digital Advantage Corp. All Rights Reserved.