目次
データベースを検索する手順
- DBをオープンする
- SQLを実行する
- 結果を取り出す
- 結果を表示する
- DBをクローズする
サンプル・プログラム
SELECT * FROM chronologic WHERE name='徳川家康';の実行を目標にしている。
では、それぞれの手順を細かく見ていくことにしよう。
解説:準備
他の文字コードも利用できるのだが、PHPバージョン5.6でUTF-8がデフォルトになったこともあり、データベースもそれに合わせておいた方が無難である。
各自の環境に合わせ、SQLiteのDBファイル名を定数 DBFILE に記述する。相対パスで記述する場合は、このスクリプトがある位置からの相対位置である。
実行するSQL文は、定数 SQL に記述する。これは、前回、SQLiteManagerで使ったものと同じである。
解説:PDOの紹介
だが、固有の関数群を使ってしまうと、後々、RDBMSを変更した際の改造コストが大きくなってしまう。
一方、「データベースを検索する手順」で述べたように、RDBMSの操作手順というのは製品によって大きな違いはない。製品固有の命令を使わなければ、SQL文も共通である。
そこでPHPバージョン5にはPDO(PHP Data Objects)クラスが用意され、RDBMSの違いに関係なく、同じプログラムでDB操作ができるようになった。
また、PHP 5.5 では、MySQLの操作方法として、固有の関数が廃止されることがアナウンスされた。SQLite 固有の関数は引き続きサポートされるが、せっかくなので、ここでは PDO を使っていくことにする。
解説:DBへの接続
234: if (! isphp5over()) {
235: $errmsg = 'PHP5以上でないと動作しません.';
236: } else if (! isSQLiteReady()) {
237: $errmsg = 'SQLiteが利用できません.';
238: } else {
239: $errmsg = '';
240: try {
241: $pdo = new PDO('sqlite:' . DBFILE);
242: $pdo->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);
243: } catch (PDOException $e) {
244: $errmsg = 'SQLite : ' . $e->getMessage();
245: }
246: }
SQLite DBファイル DBFILE へ接続するには、PDOオブジェクトを生成する。引数は、データソース名(DSN:Data Source Name)である。
DSN は、PDO を使って様々なRDBMSに接続するための識別子である。
たとえば SQLite であれば、"sqlite:DBファイル名" のように指定する。
MySQL なら、"mysql:host=ホスト名;dbname=DB名" のように指定し、第2引数でユーザー名を、第3引数でパスワードを指定する。
その他のRDBMSについては、「PDO ドライバ」を参照していただきたい。
DB接続の際(PDOインスタンス生成時)に例外をキャッチアップしている。PHP 8.3では、SQLite3で例外を使うことが推奨されるようになった。警告は将来のバージョンで削除されるとのこと。
オブジェクトが生成できたら、PDO::setAttribute を使って属性を設定する。ここでは、ATTR_ERRMODE(エラーレポート)として、ERRMODE_EXCEPTION(例外を投げる)を設定する。DB接続に失敗したら、catchでメッセージを受け取るようにしている。
解説:SQLの実行
203: foreach ($pdo->query($sql) as $row) {
204: $res .=<<< EOT
205: <tr>
206: <td class="index">{$row['name']}</td> <!-- カラム name -->
207: <td class="year">{$row['birth']}</td> <!-- カラム birth -->
208: <td class="year">{$row['death']}</td> <!-- カラム death -->
209: <td class="comment">{$row['comment']}</td> <!-- カラム comment -->
210: </tr>
211:
212: EOT;
213: }
冒頭で、DB操作はファイル操作とほとんど同じと述べたが、SELECT文は、テキストファイルから1行ずつデータを取り込むのに似ている。
PDO::query を使うと、関数 fgets を使って1行ずつ読み込むように、for 文を使ってマッチしたデータを1レコードずつ読み込むことができる。
PDO::query は、最初の関数コールの中でSQL文を実行し、結果があれば PDOStatement オブジェクトとして返す。
foreach 文と組み合わせることで、PDO::query が失敗するまで繰り返せば、1レコードずつデータを読み込むことができる。PDO::exec とは異なり、2週目からは PDOStatement オブジェクトからデータを取り出すので、パフォーマンスが低下することもない。
あとは、取り出したオブジェクトを配列 $row に入れ、それを画面表示するためのHTML文に変換するだけである。
解説:DBの解放
256: $pdo = NULL;
サンプル・プログラム:徳川家康の生年・没年を取得
解説:一部カラムを取り出すSQL文
51: //実行するSQL
52: define('SQL', "SELECT birth, death FROM chronologic WHERE name='徳川家康';");
2つのSQL文を比較してみよう。
SELECT * FROM chronologic WHERE name='徳川家康';上がすべてのカラムを取り出すSQL文、下がbirth, death カラムだけ取り出すSQL文である。SELECT と FROM の間の表現が違う。
SELECT birth, death FROM chronologic WHERE name='徳川家康';
SELECTの直後にアスタリスク(*)を記述すると全てのカラムを、カラム名をカンマ(,)で区切った場合には指定したカラムだけ取り出す指示になるのだ。
解説:カラムを数値で指定する
200: foreach ($pdo->query($sql) as $row) {
201: $res .=<<< EOT
202: <tr>
203: <td class="year">{$row[0]}</td> <!-- カラム birth -->
204: <td class="year">{$row[1]}</td> <!-- カラム death -->
205: </tr>
206:
207: EOT;
208: }
参考サイト
- SQLite関数:PHPファン
- (PHP)PDOで、SQLiteにアクセスしてみた:3流プログラマのメモ書き
- (PHP) SQLiteでカラム名を取得する
なお、PHPバージョン5以上を対象としている。SQLiteへの接続とSQL文の実行については、データベースに依存しない方式である PDO(PHP Data Objects)クラスを利用する。
(2023年11月26日)PHP8.3に関する記事を追加
(2022年11月13日)PHP8対応,他.