はじめに
PHP界隈では現在、PHP 4からPHP 5への移行が進んできており、ここ最近ではPHP 5の機能を活用したフレームワークも多く出てくるようになりました。
PHP 5は、PHP 4に比べオブジェクト指向のサポートや速度面での向上などが取り上げられる中、最も注目すべき点であるデータベースへのアクセスを抽象化したレイヤーとしてPDOが登場しました。
今回はそのPDOに注目し、サンプルを交えてPDOの使い方を紹介します。
対象読者
- PHP 5を使ったことがある方
- 以前PEAR::DBなどを用いてデータベースを使ったアプリケーションを作成したことのある方
必要な環境
PDOはPHP 5.1から標準で導入されるようになりました。Windows/UNIXを問わず利用することができます。よってPHP 5.1の環境と、PDOの動作に必要なデータベースの構築を行ってください。
PDOとは
PDO(PHP Data Object)は、PHP 5から利用できるデータアクセス抽象化レイヤです。PDOを利用すると、高機能で共通化されたインターフェイスとPHP 5の機能をふんだんに使ったデータアクセスを実現できます。
PDOと同様の仕組みとしてPEAR::DBやCreoleなどがありますが、それらはPHPで用意されているネイティブドライバ(ネイティブ関数)をPHPスクリプトでラッピングしているため、実効速度が遅いなどの問題が生じます。PDOはPHPスクリプトとネイティブドライバの組合せでは無く、PHP Extension(PHP拡張)として利用できるため、速度面ではさほど心配は要らないでしょう。
また、PDOは主要なデータベースのほとんどをサポートしているので、PEAR::DBなどからの移行も比較的容易です。
そして、PDOはPHP 5で実装された例外処理も扱えるため、PEAR::DBなどで例外処理に悩んだ開発者にとって有効な選択肢であると言えます。
ここで注意して欲しいのは、PDOはデータベースへのアクセスを抽象化するためのクラス群であり、O/Rマッピングツールが行っているようなデータベースの抽象化を行うレイヤではないということです。
PEAR::DBとの違い
PEAR::DBやPEAR::MDBなどは、PHPで用意されている多くのネイティブなデータベースアクセスのための関数をPHPスクリプトでまとめ、共通のAPIを提供しています。
しかしながら、その共通のAPIを提供している部分はPHPスクリプトで書かれているため、速度面での期待はできません。
また、PHP 5で開発している開発者にとって、PHP 4で実装が進んでいるこれらのレイヤークラス群は例外処理などで歯がゆい思いをしていると思います。
ネイティブ関数群との違い
PHPには多くのデータベースに対応している、データベース固有の関数群があります。
このようなデータベース固有のネイティブドライバは速度面での期待はもちろん、データベース特有の機能を使える半面、データベースごとに用意されている関数が共通化されていません。
また、これらの関数もやはり、PHP 5に特化されているとは言いがたいものが多いです。
インストール
PDOはPHP 5.1から標準で搭載されるようになりました。使用しているPHPのバージョンが5.1以降ならば、以下の設定を「php.ini」に追加するだけでPDOを利用することができます。
extension=pdo.so extension=pdo_mysql.so extension=pdo_pgsql.so extension=pdo_sqlite.so extension=pdo_firebird.so extension=pdo_dblib.so extension=pdo_oci.so
extension=php_pdo.dll extension=php_pdo_firebird.dll extension=php_pdo_mysql.dll extension=php_pdo_oci.dll extension=php_pdo_oci8.dll extension=php_pdo_odbc.dll extension=php_pdo_pgsql.dll extension=php_pdo_sqlite.dll
もし、PDOのモジュールがインストールされていない場合でも、以下のコマンドで簡単にインストールすることができます。
pecl install pdo
以下のコマンドを使い、個別のPDOドライバをインストールすることもできます。
pecl install pdo_pgsql
Windows環境でPDOのDLLが無い場合は、PECL4WINを利用して必要なライブラリを取得することもできます。
PDOの簡単な使い方
最も簡単なPDOの使い方を見てみましょう。今回使用するデータベースのテーブルは、以下のものを用意しました。
ID | TITLE | CONTENT |
1 | HAPPY | HAPPY SONG |
2 | SAD | SAD SONG |
3 | ANGRY | ANGRY SONG |
4 | LOVE | LOVE SONG |
5 | SLEEPY | SLEEPY SONG |
6 | CHRISTMAS | CHRISTMAS SONG |
7 | NEW YEAR | NEW YEAR SONG |
Isbn | Title | Author |
689847432 | Alices Adv | Robert |
2147483647 | Davinci Code | Dan |
321127420 | PofEAA | Martin Fowler |
1932394150 | Hibernate in Action | Gavin King |
テーブル定義は次のとおりです。
CREATE TABLE CD( ID INTEGER NOT NULL, TITLE VARCHAR(100), CONTENT VARCHAR(200), PRIMARY KEY(ID) ); CREATE TABLE BOOK( Isbn INT NOT NULL, Title VARCHAR(255) DEFAULT "", Author VARCHAR(100), PRIMARY KEY(ISBN) );
PDOでDBへ接続/切断(connection/disconnection)
PDOによるデータベースへの接続/切断は、非常に簡単に実装されています。
try { // MySQLサーバへ接続 $pdo = new PDO("mysql:host=localhost; dbname=pdotest", "root", "password"); } catch(PDOException $e){ var_dump($e->getMessage()); } // 切断 $pdo = null;
データベースへの接続は、PDOのコンストラクタに「DSN」と、データベースへアクセスする「ユーザー名」「パスワード」を指定するだけです(PDOのコンストラクタの引数については後ほど解説します)。
また、このPDOオブジェクトを開放すると、データベースから切断されます。そのため、PDOオブジェクトにnullを代入したりunset()
を実行するだけで簡単にデータベースから切断することができます。
ここでcatchしているPDOException
は、接続に失敗した場合などに投げられる例外です。PDOException
自体は接続/切断以外にもいろいろな場所から投げられるので、開発者は適切な例外処理を記述しやすくなります。
PDOでデータの取得(SELECT)
SELECT
文を発行する例です。
try { $pdo = new PDO("mysql:host=localhost; dbname=pdotest", "root", "pass"); $stmt = $pdo->query("SELECT * FROM CD"); while($row = $stmt->fetch(PDO::FETCH_ASSOC)){ echo implode(", ", $row) . PHP_EOL; } } catch (PDOException $e){ var_dump($e->getMessage()); } $pdo = null;
今回の結果は次のようになります。
1, HAPPY, HAPPY SONG 2, SAD, SAD SONG 3, ANGRY, ANGRY SONG 4, LOVE, LOVE SONG 5, SLEEPY, SLEEPY SONG 6, CHRISTMAS, CHRISTMAS SONG 7, NEW YEAR, NEW YEAR SONG
PDOでデータの追加・更新・削除(INSERT/UPDATE/DELETE)
データを追加する簡単な例です。
$ids = array(10, 11, 12); $titles = array('COUNTRY', 'PARTY', 'QUIZ'); $contents = array('Country Song', 'Party Music', 'Quiz Song'); try { $pdo = new PDO( "mysql:host=localhost; dbname=pdotest", "root", "pass"); $stmt = $pdo->prepare( "INSERT INTO CD(ID, TITLE, CONTENT) VALUES(:ID, :TITLE, :CONTENT)"); for($i = 0; $i < 3; $i++){ $stmt->bindValue(':ID', $ids[$i]); $stmt->bindValue(':TITLE', $titles[$i]); $stmt->bindValue(':CONTENT', $contents[$i]); $stmt->execute(); } } catch (PDOException $e){ var_dump($e->getMessage()); } $pdo = null;
PDO::prepare()
やPDOStatement::bindValue()
については後ほど解説します。ここで、先ほど作成したSELECT
文を発行するスクリプトを実行してみましょう。
1, HAPPY, HAPPY SONG 2, SAD, SAD SONG 3, ANGRY, ANGRY SONG 4, LOVE, LOVE SONG 5, SLEEPY, SLEEPY SONG 6, CHRISTMAS, CHRISTMAS SONG 7, NEW YEAR, NEW YEAR SONG 10, COUNTRY, Country Song 11, PARTY, Party Music 12, QUIZ, Quiz Song
無事追加されていることが確認できました。
それではこれらの処理を深く追っていきましょう