データアクセスオブジェクト (DAO)
データアクセスオブジェクト (DAO) は、異なるデータベース管理システム (DBMS) 上に保存されたデータに接続するための包括的な API を提供します。 DAO を用いてデータにアクセスすることで、コードを変更せずに異なる DBMS を利用する事が可能になります
Yii DAO は MySQL や PostgreSQL といった多くのポピュラーな DBMS への統一的なデータアクセスを提供する PHP Data Objects (PDO) 拡張を用いて構築されています。
そのため、Yii DAO を利用するには、PDO 拡張と特定の PDO データベースドライバ (たとえば PDO_MYSQL
) がインストールされている必要があります。
Yii DAO は、主に以下の 4 つのクラスから構成されています:
- CDbConnection: データベースとの接続を表します。
- CDbCommand: データベースに対して実行する SQL 文を表します。
- CDbDataReader: クエリ結果セットからの後戻りしないストリームを表します。
- CDbTransaction: DB トランザクションを表します。
以下に、さまざまなシナリオでの Yii DAO の使用方法を紹介します。
データベース接続の確立
データベース接続を確立させるには、CDbConnection のインスタンスを作成して active にします。 データソース名 (DSN) がデータベースに接続するために要求される情報を指定するために必要です。 おそらく username と password も接続を確立させるために必要でしょう。 接続を確立する際にエラーが起こると例外が発生します (たとえば、間違った DSN や無効な username/password)。
DSN のフォーマットは、使用する PDO データベースドライバに依存します。 一般的には、DSN はその PDO ドライバ名に続けてコロン、その後に、ドライバ個別の接続シンタックスを指定します。 詳細な情報は、PDO documentation を参照してください。 以下に、一般に用いられる DSN フォーマットのリストを示します:
- SQLite:
sqlite:/path/to/dbfile
- MySQL/MariaDB:
mysql:host=localhost;dbname=testdb
- PostgreSQL:
pgsql:host=localhost;port=5432;dbname=testdb
- SQL Server:
mssql:host=localhost;dbname=testdb
- Oracle:
oci:dbname=//localhost:1521/testdb
CDbConnection は CApplicationComponent から拡張されているため、アプリケーションコンポーネント として使用できます。
そうするには、アプリケーション初期構成 内で db
という名前 (もしくは他の名前) のアプリケーションコンポーネントを下記のように設定します。
その後、CDbConnection::autoConnect 設定が false になっていない限り、すでに自動的にアクティブになっている Yii::app()->db
を利用してDB 接続にアクセスできます。
このアプローチを使うと、単一の DB 接続をコード中の色々な場所で共有することができます。
SQL 文の実行
一度データベース接続を確立すれば、CDbCommand を使用して SQL 文を実行できます。 まず、特定の SQL 文によって CDbConnection::createCommand() を呼び、CDbCommand のインスタンスを作成します:
SQL 文は、次の2つの方法のうちのいずれかで、CDbCommand によって実行されます:
execute():
INSERT
,UPDATE
,DELETE
のような、非クエリ型の SQL 文を実行します。 成功した場合、SQL 文の実行によって影響された行数を返します。query():
SELECT
のような、データ行を返す SQL 文を実行します。 成功した場合、結果の行を読み出すことが出来る CDbDataReader インタンスが返されます。 便宜上、直接クエリ結果の行を返す一連のqueryXXX()
メソッドも実装されています。
SQL 文の実行中にエラーが発生した場合は、例外が発生します。
クエリ結果の取得
CDbCommand::query() により CDbDataReader インスタンスを生成した後に、CDbDataReader::read() を繰り返し呼ぶことで、結果データの行を取り出せます。
データを一行ずつ取り出すために、PHP の foreach
文の中で CDbDataReader を使用できます。
注意: query() と異なり、全ての
queryXXX()
メソッドは直接データを返します。 たとえば、queryRow() は、クエリ結果の最初の行を表現する配列を返します。
トランザクションの使用
アプリケーションがいくつかのクエリを実行して、各クエリがデータベース中の情報を読み書きする場合は、クエリのどれかが実行されずに残る、という事が無いように確認することが重要です。 Yii の CDbTransaction インスタンスとして表されるトランザクションは、このような場合に開始できます:
- トランザクションを開始する。
- 一つずつクエリを実行する。データベースへのどんな更新も外の世界には見えません。
- トランザクションをコミットする。処理が成功した場合、更新が適用されます。
- もしクエリのひとつが失敗した場合、全処理がロールバックされます。
上記のワークフローは次のコードを使用して実装できます:
パラメータのバインディング
SQL インジェクション攻撃 を避け、繰り返し使用される SQL 文の実行パフォーマンスを改善するために、SQL 文とオプションのパラメータプレースホルダを "準備 prepare" することが出来ます。 プレースホルダは、パラメータバインディングの過程で、実引数と置き換えられることになっています。
パラメータプレースホルダは、名前付き (ユニークなトークンとして表される) か、無名 (クエスチョンマークとして表わされる) かのどちらかを使えます。 CDbCommand::bindParam() か CDbCommand::bindValue() を呼び出す事で、これらのプレースホルダを実引数に置き換えます。 パラメータを引用符で囲む必要はありません。下層のデータベースドライバがその処理を行なってくれます。 パラメータバインディングは、SQL 文を実行する前に行われなければなりません。
bindParam() メソッドと bindValue() メソッドは、とても似ています。 唯一の違いは、前者はパラメータにバインドするのに PHP 変数の参照を使い、後者は変数の値を使うということです。 大きなメモリブロックで表わされるデータをパラメータに指定する場合は、パフォーマンス的に前者の方法を利用する事を推奨します。
バインディングパラメータについての詳細については、関連する PHP ドキュメント を参照してください。
カラムのバインディング
クエリの結果を抽出 (フェッチ) する場合、カラムを PHP 変数にバインドすることで、一行抽出されるごとに、変数に最新のデータが自動的に入るようにする事ができます。
テーブルプレフィックスを使う
Yii はテーブルプレフィックスの使用について、統合的なサポートを提供しています。
テーブルプレフィックスとは、現在接続されているデータベースのテーブル名の前に付加されている文字列を意味します。
たいていは、共有ホスティング環境において使われます。複数のアプリケーションが単一のデータベースを共有しつつ、お互いを区別するために違うテーブルプレフィックスを使うという形です。
例えば、あるアプリケーションは tbl_
をプレフィックスとして使い、他のアプリケーションは yii_
を使うという具合です。
テーブルプレフィックスを使うためには、CDbConnection::tablePrefix プロパティを望みのテーブルプレフィックスに構成します。
そして、SQL 文においてテーブル名を指定するのに {{TableName}}
という書式を使います。
ここで TableName
はプレフィックスを除外したテーブル名を指します。
例えば、データベースが tbl_user
という名前のテーブルを持っていて、tbl_
がテーブルプレフィックスとして構成されている場合、ユーザに関するクエリのコードとして下記を使うことが出来ます。