PDO入門

PDOとは

PDO(PHP Data Objects)はPHPに標準搭載されているデータベースアクセス抽象化ライブラリです。 データベースの違いを吸収し、共通の関数でデータベースを操作することを可能にしています。

データベースへの接続

PDOでデータベースと接続するときは、クラスのインスタンス化と同様の手段で行います。

$PDOのオブジェクト = new PDO('DNS文字列', 'DBユーザー名', 'DBパスワード');

DNS文字列

DNSとは、Data Source Nameの略で、データベースに必要な情報となるデータソース名のことです。
データベースにより要素が異なりますが
MySQLの場合、
  • dbname : データベース名
  • host : ホスト名
  • port : ポート番号
から構成されます。
ホスト名と、ポート番号の代わりに
  • unix_socket : Unixソケット
を指定することも出来ます。

それぞれの要素の順番には意味はありません。
書式は下のようになります。
mysql:dbname=データベース名;host=ホスト名;port=ポート番号

PDOによるデータベース接続のサンプル

  • データベース名 : testbase
  • ホスト名 : localhost
  • ポート番号 : 8889
  • DBユーザー名 : testuser
  • DBパスワード : pass

上記のデータベースに接続する場合、

<?php
$pdoObject = new PDO('mysql:dbname=testbase;host=localhost;port=8889', 'testuser', 'pass');
このようになります。

データベース接続を解除する

接続時に生成されたPDOオブジェクトを破棄することで接続を解除できます。
明示的に破棄しない場合はPHPスクリプトの終了時に接続が解除されます。

<?php
$pdoObject = new PDO('mysql:dbname=testbase;host=localhost;port=8889', 'testuser', 'pass'); //接続
unset($pdoObject); //接続解除

プリペアドステートメントとクエリの実行

ここではPDOのprepareメソッドを使ってSQL文を実行する方法を紹介します。

prepareメソッド

prepareメソッドはSQL文を実行する準備を行います。
PDOオブジェクト に対してのみ使用することができます。
メソッドの返り値はPDOStatementオブジェクトになります。

引数にはSQL文を入れます。SQL文中にプレースホルダとして疑問符「?」を使うことができます。
動的にSQL文を変えたい場合は、変えたい部分に疑問符を使います。

例:

<?php
$pdoObject = new PDO('mysql:dbname=testbase;host=localhost;port=8889', 'testuser', 'pass');
$pdoStatementObject = $pdoObject->prepare("SELECT * FROM user WHERE id = ?");
上記の例の場合、idはこの時点では定まっておらず、後から動的に指定することができます。
SQL文を実行する準備が出来ただけであり、この時点ではSQLは実行されません。

executeメソッド

executeメソッドはprepareメソッドで準備したSQL文を実行します。
このメソッドは PDOStatementオブジェクト に対してのみ実行することができます。
引数にはprepareメソッドで疑問符「?」を記述した部分を配列形式で順番に指定します。

例:

<?php
$pdoObject = new PDO('mysql:dbname=testbase;host=localhost;port=8889', 'testuser', 'pass');
$pdoStatementObject = $pdoObject->prepare("SELECT * FROM user WHERE id = ?");
$pdoStatementObject->execute(array('uteam')); //idがuteamだった場合
$pdoStatementObject->execute(array('uhero')); //idがuheroだった場合
executeメソッドは複数回実行可能です。
上記の例の場合、一度prepareメソッドを実行した後はexecuteメソッドの引数を変えるだけで他のIDでSQL文を実行することが出来ます。
結果の取得方法は後の項目で解説します。

プリペアドステートメントを使わないクエリの実行

プリペアドステートメントを使わない方法もあります。
SQL文を一度しか使わず、パラメータが存在しない場合に便利です。

queryメソッド

queryメソッドはSQL文を実行します。
PDOオブジェクト に対してのみ使用することができます。
メソッドの返り値はprepareメソッドと同じくPDOStatementオブジェクトになります。

引数にはSQL文を入れます。

例:

<?php
$pdoObject = new PDO('mysql:dbname=testbase;host=localhost;port=8889', 'testuser', 'pass');
$pdoStatementObject = $pdoObject->query("SELECT name FROM user");
prepareメソッドと異なり、この時点でSQL文が実行されデータベースに問い合わせを行います。

execメソッド

execメソッドもqueryメソッド同じくSQL文を実行しますが、
返り値は、PDOStatementオブジェクトではなく、そのSQL文により削除または更新された行数となっております。
UPDATE文やDELETE文などでのみ有効です。SELECT文からは結果は返りません。

例:

<?php
$pdoObject = new PDO('mysql:dbname=testbase;host=localhost;port=8889', 'testuser', 'pass');
$count = $pdoObject->exec("DELETE FROM user WHERE name = '山田'");
echo $count . '行削除されました。';

結果の取得

SQL文を実行した結果を取得する操作は全てprepareメソッドやqueryメソッドにより生成された
PDOStatementオブジェクト に対して実行します。

fetchメソッド

fetchメソッドは結果から単一の行を取得します。公式リファレンスでは「次の行を取得する」と書かれています。
実行結果が1行しかない場合や、1行ずつ取得するときに使います。
実行した行はPDOStatementオブジェクトから削除されるため、ループ文で次々取得するような書き方も可能です。

例1:
<?php
$pdoObject = new PDO('mysql:dbname=testbase;host=localhost;port=8889', 'testuser', 'pass');
$pdoStatementObject = $pdoObject->prepare("SELECT name,address FROM user WHERE id = ?"); //IDに重複は無いとする。
$pdoStatementObject->execute(array('uteam')); //idがuteamだった場合
$row = $pdoStatementObject->fetch();
echo $row['name'];//IDに重複がなければ、IDに対応するカラム名nameの値が取得可能
例2:
<?php
$pdoObject = new PDO('mysql:dbname=testbase;host=localhost;port=8889', 'testuser', 'pass');
$pdoStatementObject = $pdoObject->query("SELECT name,address FROM user");
while ($row = $pdoStatementObject->fetch()){ //実行した行は削除されていくため、nullになるまでループする。
        echo $row['name'];
}

fetchAllメソッド

fetchAllメソッドは結果の全ての行を配列で取得します。
実行結果が複数行になる場合に、まとめて取得したい場合に使います。
例:
<?php
$pdoObject = new PDO('mysql:dbname=testbase;host=localhost;port=8889', 'testuser', 'pass');
$pdoStatementObject = $pdoObject->query("SELECT name,address FROM user");
$rows = $pdoStatementObject->fetchAll();
foreach ($rows as $row){
        echo $row['name'];
}

FETCHモード

fetchメソッドやfetchAllメソッドの第1引数に、FETCHモードを指定することで、結果として取得する配列の書式を切り替えることが出来ます。
デフォルトではFETCH_BOTHになっており、結果配列の中には「カラム名をキー」と「カラムに割り当てられた連番をキー」の両方に同じ値が2重に入っています。
FETCH_ASSOCと指定すると、「カラム名をキー」のみになり、FETCH_NUMと指定すると「カラム名を数字」のみになります。
また、$pdoStatementObject->setAttribute(PDO::FETCH_ASSOC); とすることデフォルトの設定を変えることが出来ます。

エラー処理

PDOには3つのエラー処理方法があります。
デフォルトは PDO::ERRMODE_SILENT です。
PDOオブジェクト に対してsetAttributeメソッドでエラーモードをセットすることで
設定することができます。

例1:
<?php
$pdoObject->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_SILENT);

PDO::ERRMODE_SILENT

PDOはエラーコードのみを設定します。
そのエラーコードを取得するには、errorCodeメソッドとerrorInfoメソッドをPDOオブジェクトかPDOStatementオブジェクトに対して実行します。

PDO::ERRMODE_WARNING

これを設定すると、PHPでは伝統的なE_WARNINGメッセージを出力します。デバック時に有効です。

PDO::ERRMODE_EXCEPTION

PDOException をスローします。
このモードが有用である理由のひとつとして、伝統的な PHP 形式の警告よりも より明確にエラー処理コードが書けることがあります。
例外を発生させず、 データベースへのコールのたびに毎回明示的に返り値をチェックすることに 比べると、コードの量やネストを減らすことができます。
PDOExceptionはRuntimeExceptionを継承した例外クラスです。
PDOの内部で発生した例外を表します。
ユーザー自身が書いたコードからPDOExceptionをスローしてはいけません。
PDOExceptionのgetCodeメソッドを実行することで、SQL文を取得可能です。
例:
<?php
try {
    //PDOはtry~catch構文の内側で実行します。
    $pdoObject = new PDO('mysql:dbname=testbase;host=localhost;port=8889', 'testuser', 'pass');
    $pdoObject->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);
} catch (PDOException $e) {
    echo '接続に失敗しました: ' . $e->getMessage();
}
このドキュメントは Sphinx 1.2.1 で生成しました。