==================== PDO入門 ==================== PDOとは ============================ PDO(PHP Data Objects)はPHPに標準搭載されているデータベースアクセス抽象化ライブラリです。 データベースの違いを吸収し、共通の関数でデータベースを操作することを可能にしています。 データベースへの接続 ========================== PDOでデータベースと接続するときは、クラスのインスタンス化と同様の手段で行います。 .. code-block:: php $PDOのオブジェクト = new PDO('DNS文字列', 'DBユーザー名', 'DBパスワード'); DNS文字列 -------------- | DNSとは、Data Source Nameの略で、データベースに必要な情報となるデータソース名のことです。 | データベースにより要素が異なりますが | MySQLの場合、 * dbname : データベース名  * host : ホスト名 * port : ポート番号 | から構成されます。 | ホスト名と、ポート番号の代わりに * unix_socket : Unixソケット | を指定することも出来ます。 | | それぞれの要素の順番には意味はありません。 | 書式は下のようになります。 .. code-block:: none mysql:dbname=データベース名;host=ホスト名;port=ポート番号 PDOによるデータベース接続のサンプル ----------------------------------- * データベース名 : testbase * ホスト名 : localhost * ポート番号 : 8889 * DBユーザー名 : testuser * DBパスワード : pass 上記のデータベースに接続する場合、 .. code-block:: php prepare("SELECT * FROM user WHERE id = ?"); | 上記の例の場合、idはこの時点では定まっておらず、後から動的に指定することができます。 | SQL文を実行する準備が出来ただけであり、この時点ではSQLは実行されません。 executeメソッド ------------------------------- | executeメソッドはprepareメソッドで準備したSQL文を実行します。 | このメソッドは **PDOStatementオブジェクト** に対してのみ実行することができます。 | 引数にはprepareメソッドで疑問符「?」を記述した部分を配列形式で順番に指定します。 例: .. code-block:: php 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文を入れます。 例: .. code-block:: php query("SELECT name FROM user"); | prepareメソッドと異なり、この時点でSQL文が実行されデータベースに問い合わせを行います。 execメソッド ---------------------------- | execメソッドもqueryメソッド同じくSQL文を実行しますが、 | 返り値は、PDOStatementオブジェクトではなく、そのSQL文により削除または更新された行数となっております。 | UPDATE文やDELETE文などでのみ有効です。SELECT文からは結果は返りません。 例: .. code-block:: php exec("DELETE FROM user WHERE name = '山田'"); echo $count . '行削除されました。'; 結果の取得 ================ | SQL文を実行した結果を取得する操作は全てprepareメソッドやqueryメソッドにより生成された | **PDOStatementオブジェクト** に対して実行します。 fetchメソッド --------------------- | fetchメソッドは結果から単一の行を取得します。公式リファレンスでは「次の行を取得する」と書かれています。 | 実行結果が1行しかない場合や、1行ずつ取得するときに使います。 | 実行した行はPDOStatementオブジェクトから削除されるため、ループ文で次々取得するような書き方も可能です。 | | 例1: .. code-block:: php 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: .. code-block:: php query("SELECT name,address FROM user"); while ($row = $pdoStatementObject->fetch()){ //実行した行は削除されていくため、nullになるまでループする。 echo $row['name']; } fetchAllメソッド ------------------------ | fetchAllメソッドは結果の全ての行を配列で取得します。 | 実行結果が複数行になる場合に、まとめて取得したい場合に使います。 | 例: .. code-block:: php 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: .. code-block:: php 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文を取得可能です。 | 例: .. code-block:: php setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION); } catch (PDOException $e) { echo '接続に失敗しました: ' . $e->getMessage(); }