This project is no longer maintained and has been archived.

DoctrineはDoctrine_Queryインスタンスを ユーザーが利用できるPHPのデータに変換するためのデータハイドレーターの概念を持ちます。データをハイドレイトするもっとも明らかな方法はこれをオブジェクトグラフに入れるとモデル/クラスインスタンスが返されることです。ときにはデータを配列にハイドレイトしたい場合、ハイドレーションを使わないと単独のスカラーの値が買えされます。この章は異なるハイドレーションのタイプおよび独自のハイドレーションのタイプの書き方もデモンストレートします。

コアハイドレーションメソッド

Doctrineはもっとも共通のハイドレーションのニーズによってあなたを助けてくれる少数のコアのハイドレーションメソッドを提供します。

レコード

最初のタイプはHYDRATE_RECORDでこれはデフォルトのハイドレーションのタイプです。これはクエリからデータをとりこれはオブジェクトグラフにハイドレイトします。このタイプによった次のようなことが可能になります。

$q = Doctrine_Core::getTable('User') ->createQuery('u')

->leftJoin('u.Email e') ->where('u.username = ?', 'jwage');

$user = $q->fetchOne(array(), Doctrine_Core::HYDRATE_RECORD);

echo $user->Email->email;

上記のクエリのデータは1つのクエリによって検索されレコードハイドレーターによってオブジェクトグラフにハイドレイトされました。データベースからの結果セットではなくレコードは扱うのが難しいので、これによってデータを扱うのがはるかに簡単になります。

配列

配列ハイドレーションタイプはHYDRATE_ARRAY定数によって表現されます。PHPオブジェクトを使ってデータをオブジェクトグラフにハイドレイトする代わりにPHP配列を使うこと以外、上記のレコードハイドレーションは理想的です。オブジェクトの代わりに配列を使う利点はこれらがずっと速くハイドレーションは時間がかからないことです。

同じ結果を実行したい場合、同じデータにアクセスできますが、PHP配列経由になります。

$q = Doctrine_Core::getTable('User') ->createQuery('u')

->leftJoin('u.Email e') ->where('u.username = ?', 'jwage');

$user = $q->fetchOne(array(), Doctrine_Core::HYDRATE_ARRAY);

echo $user['Email']['email'];

スカラー

スカラーハイドレーションタイプはHYDRATE_SCALAR定数によって表現されデータをハイドレイトするためにとても速くて効率的な方法です。この方法の欠点はこれはデータをオブジェクトグラフにハイドレイトしないことで、これはたくさんのレコードを扱うときに扱いにくいフラットな長方形の結果セットを返します。

$q = Doctrine_Core::getTable('User') ->createQuery('u')

->where('u.username = ?', 'jwage');

$user = $q->fetchOne(array(), Doctrine_Core::HYDRATE_SCALAR);

echo $user['u_username'];

上記のクエリは次のようなデータ構造を生み出します:

$user = array( 'u_username' => 'jwage', 'u_password' => 'changeme',

// ... );

クエリがデータよりもJOINされた多くのリレーションシップを持つ場合 ユーザーが存在するすべてのレコードでユーザーが重複することになります。これはたくさんのレコードを扱うときに扱いが難しいので欠点です。

シングルスカラー

単独のスカラー値だけを返したいことがよくあります。これはシングルスカラーハイドレーションの方法で可能でHYDRATE\_SINGLE_SCALAR属性によって表現されます。

このハイドレーションタイプによって次のように1人のユーザーが持つ電話番号の数を簡単に数えることができます:

$q = Doctrine_Core::getTable('User') ->createQuery('u')

->select('COUNT(p.id)') ->leftJoin('u.Phonenumber p') ->where('u.username = ?', 'jwage');

$numPhonenumbers = $q->fetchOne(array(), Doctrine_Core::HYDRATE_SINGLE_SCALAR);

echo $numPhonenumbers;

これはより複雑な方法でデータをハイドレイトしてこれらの結果から値を得るよりもはるかによい方法です。これによって本当に欲しいデータをとても速く効率的に得ることができます。

オンデマンド

よりメモリーの使用量が少ないハイドレーションの方法を使いたいのであればHYDRATE\_ON_DEMAND定数によって表現されるオンデマンドハイドレーションを使うことができます。これは一度の1つのレコードグラフのみをハイドレイトするので使われるメモリーがより少なくて済むことを意味します。

// Doctrine_Collection_OnDemandのインスタンスを返す $result =

q->execute(array(), Doctrine_Core::HYDRATE_ON_DEMAND); foreach (resultas $obj) { // ... }

Doctrine\_Collection_OnDemandはイテレートするときに一度にそれぞれのオブジェクトをハイドレイトするのでこの結果はより少ないメモリーで済みます。これは最初にデータベースからすべてのデータをPHPにロードし、返すデータ構造全体を変換する必要がないからです。

入れ子集合のレコード階層

入れ子集合のビヘイビアを使うモデルのために、入れ子集合のツリーを入れ子オブジェクトの実際の階層にハイドレイトするレコード階層ハイドレーションの方法を使うことができます。

$categories = Doctrine_Core::getTable('Category') ->createQuery('c')

->execute(array(), Doctrine_Core::HYDRATE_RECORD_HIERARCHY);

これで\__childrenという名前のマッピングされた値のプロパティにアクセスすることでレコードの子にアクセスできます。名前の衝突を避けるためにこの名前にはプレフィックスとしてアンダースコアがつけられています。

foreach ($categories->getFirst()->get('__children') as $child) { //

... }

入れ子集合の配列階層

入れ子集合階層をオブジェクトではなく配列にハイドレイトしたい場合HYDRATE\_ARRAY\_HIERARCHY定数を使ってこれを実現できます。これはオブジェクトの代わりにPHP配列を使っている以外はHYDRATE\_RECORD_HIERARCHYと同じです。

$categories = Doctrine_Core::getTable('Category') ->createQuery('c')

->execute(array(), Doctrine_Core::HYDRATE_ARRAY_HIERARCHY);

次のことができるようになります:

foreach ($categories[0]['__children'] as $child) { // ... }

ハイドレーションメソッドを書く

Doctrineは独自のハイドレーション方法を書きこれらを登録する機能を提供します。必要なのはDoctrine\_Hydrator\_Abstractを継承するクラスを書きこれをDoctrine_Managerで登録することです。

最初にサンプルのハイドレイターのクラスを書いてみましょう:

class Doctrine_Hydrator_MyHydrator extends

Doctrine_Hydrator_Abstract { public function hydrateResultSet($stmt) { $data = $stmt->fetchAll(PDO::FETCH_ASSOC); // $dataで何かを行う return $data; } }

これを使うためにはDoctrine_Managerで登録します:

// bootstrap.php

// ... $manager->registerHydrator('my_hydrator', 'Doctrine_Hydrator_MyHydrator');

クエリを実行するとき、my_hydratorを渡せばデータをハイドレイトするクラスが使われます。

$q->execute(array(), 'my_hydrator');