Orm
ORMはオブジェクト
関係マッピングの略です。 これは、2つのことを行います: オブジェクトにデータベースのテーブルの行をマップし、
それはあなたがそれらのオブジェクト間の関係を確立することができます。
それは
Active Record パターンに従いますが、 他のシステムに影響も受けます。
Relations: はじめに
設定
基本的な設定
protected static $_has_many = array('comments');
例えば、Model_Articleで指定した場合、
コメントインスタンスを通して主要なキーにマッチしているフィールドarticle_idを持つ多数の
Model_Commentオブジェクトとして取得する事を可能にします。
完全な設定
protected static $_has_many = array('comments' => array(
'model_to' => 'Model_Fancy_Comment',
'key_from' => 'article_id',
'key_to' => 'parent_article_id',
'cascade_save' => true,
'cascade_delete' => false,
// 特定の関係タイプのために、もう少しオプションがあります
));
基本的な例に、Ormはモデル名とフィールド・マッピングを自動的に行います。 この例は
目標モデルのクラス名をはっきりと指定します、フィールドはそれらを関連させたものです。
そして、アクションが進行中に実行したかどうかにかかわらず、オブジェクトがそうでなければならない流れはターゲットに対しカスケード(縦列)になりました。 It will return an array of
Model_Fancy_Comment オブジェクトはparent_article_idフィールドと
article_idが一致する場合に、配列を返します。 オブジェクトに操作を保持する時、
その操作は、そのロードしたリレーションに関しても実行されます。削除することはデフォルトではカスケードされませんが、
あなたがこのスイッチをONにするならば、可能です。
リレーションを取得し、それらの出力を制限するときの制限: あなたは、メインオブジェクトのステートメントを
複合して使うことができません。 それはwhere_open()を使った
ネスト状態の括弧を使っている問合わせです。問合わせがあることができる標準(非ネスト)は、問題なく適用できます。
技術的に、それはこのように働きます : 出力を制限するために、ベース・モデルのテーブルの上の問合わせは、
実は制限をそれの上に置くサブクエリです。ネストになったそれらのどの状況でも、
サブクエリとさらに加わられた関係の結果に関して適用されます。
構成オプション
最も一般的な命名規則を使用する場合の構成はすべてオプションです。
model_to |
エイリアスから計算 |
もし指定するならば, ターゲットモデルの完全なクラス名が必要です。 (例. Model_Comment).
既定では、この値はエイリアスの単数形に'Model_'を付けることにより形成されています。
(例. 'comments' は 'Model_Comment'になります)。 それは、現在のモデルと同じ
名前空間にあることにもなります。 |
key_from |
キーが、現在のモデル(通常ID)で、リレーションのために使われます |
ターゲットモデルを現在のモデルのテーブルの任意のフィールドにマップすることを許可します。 |
key_to |
現在のモデル名から算出します。 |
デフォルトでは、Model_Articleから多くのModel_Commentへの関係は、
comments テーブルのarticle_idフィールドを使用します |
cascade_save |
bool true |
カスケードすることは、モデルの活動がその関係に関して繰り返されることを意味します。 このように、
保存をカスケードすることは同様に関係を保持し、削除をカスケードすることは、
同様に関係も削除します。 カスケード削除について特に注意をしてください!
あなたは、元のモデルの delete()もしくはsave()を呼び出すときに、
最初の引数にtrueを渡すことで、実行時にこれらのオプションを無効にすることができます。 |
cascade_delete |
bool false |
conditions |
array() |
'where'と'order_by' キーを受け取ります。これらは、通常の使用よりも制限されます:
whereは配列含む配列でなければなりません。
array(field, compare, value). order_byはフィールドや連想の配列が含まれています。
field => direction.
Note: これらは常に使用され、オフにすることはできません。 |
使い方
ORMはリレーションの一括読み込みと遅延読み込みの両方を可能にします。一括読み込みは、
一部(またはすべて)のリレーションは、元の照会でフェッチされていることを意味します。 遅延読み込みは、
あなたがそれらを要求するまでリレーションがフェッチされないことを意味します。
// eager loading, using joins:
$post = Model_Post::find('all', array('related' => array('comments')));
// or
$post = Model_Post::query()->related('comments')->get();
// $post->comments is available without any further querying after this
// もしくは、遅延読み込みを使ってください。それはリレーションを使用しますが、一度要求されたリレーションを照会しません。
// 最初の "post"は、結合せずに1クエリを取得します。
$post = Model_Post::find('first');
// 自動的にjoinすることなく、別のクエリを実行される、コメントを(まだロードされていない)を要求します。
$comments = $post->comments;
// alternatively, you can use get(), which allows additional conditions:
$comments = $post->get('comments', array('where' => array(array('field', '=', $value))));
使い方 where/order_by 条件
ORMでフェッチするときにも、条件を追加することができます。 また、取得したデータだけで
それらをフェッチしているとの条件に有効であることを意味するでしょうが、注意をしてください。
追加条件は、任意のデフォルトの条件です(see config table above)。
もちろん、遅延読み込みでも、一括読み込みでも可能です。
// 照会配列を使用
$post = Model_Post::find('first', array(
'related' => array(
'articles' => array(
'order_by' => array('id' => 'desc'),
'where' => array(
array('publish_date', '>', time()),
array('published', '=', 1),
),
),
),
));
// メソッドチェーンを使用して
$post = Model_Post::query()->related('articles', array(
'order_by' => array('id' => 'desc'),
'where' => array(
array('publish_date', '>', time()),
array('published', 1), // '='を用いてそれが省略されることができるとき
),
)->get_one();
// しかし、同じことがまた列にリレーション名を付けることによって行うことができます:
$post = Model_Post::query()->related('articles')
->order_by('articles.id', 'desc')
->where('articles.publish_date', '>', time())
->where('articles.published', 1)
->get_one();
入れ子になったリレーションシップを持つ用法
それは(あなたがあまりにも多くの結合が必要なクエリーを作成注意したいかもしれませんが)
無制限の深さに関係の関係を取得することも可能です。これらのすべて、または一部は、以下に例示されている場所と
order_by を条件と組み合わせることができます。
あなたは、その関係の前に "parent" の関係をロードする必要がありリレーションの関係を取得したい場合、
order は、ここで問題となることに注意してください。それ以外の場合、例外が投げられます。
//照会配列を使用
$post = Model_Post::find('first', array(
'related' => array(
'articles' => array(
'related' => array(
'user' => array(
'related' => array('profile'),
'where' => array('active', 1),
),
),
'order_by' => array(
'published' => 'desc',
),
),
),
));
// 唯一のメソッドチェーンを使用して
$post = Model_Post::query()
->related('articles')
->related('articles.user')
->related('articles.user.profile')
->where('articles.user.active', '=', 1)
->order_by('articles.published', 'desc')
->get_one();
// または配列とメソッドチェーンを組み合わせる
$post = Model_Post::query()
->related('articles', array(
'related' => array('user' => array(
'where' => array('active' => 1),
)),
'order_by' => array('published', 'desc'),
))
->related('articles.user.profile')
->get_one();
結合の種類
デフォルトでは、ORM は 'left' join を使用してリレーションを結合します。異なるリレーションを指定するには、'join_type' 条件を使用します:
$post = Model_Post::find('first', array(
'related' => array(
'articles' => array(
'join_type' => 'inner',
'where' => array(
array('publish_date', '>', DB::expr(time())),
array('published', '=', DB::expr(1)),
),
'order_by' => array('id' => 'desc'),
),
),
));
where 句は join 前に実行されるため、 where 句が含まれている場合は OUTER JOIN にはならず、
where 句の条件は結合前フィルターのように動作します。
JOIN の条件を定義するためには以下のようにします:
$post = Model_Post::find('all', array(
'related' => array(
'articles' => array(
'join_type' => 'left outer',
'join_on' => array(
array('publish_date', '>', DB::expr(time())),
array('published', '=', DB::expr(1)),
),
'order_by' => array('id' => 'desc'),
),
),
));
これは、WHERE 句の条件の代わりに、ON 句の検索条件として追加します。
Note that if you want to pass a literal value to a join, you will have to encapsulate it in a DB::expr() to avoid it being escaped as a column name.
リレーションタイプ
ORM はネイティブに次の関係のタイプをサポートしています。
- Belongs To
そのテーブルにリレーションを保持する主キーを持つ、1関連オブジェクトに属します。
- Has One
別のテーブル(これに属する)のいずれかの他の行に保存され、その主キーは、
1関連オブジェクトを持っています。
- Has Many
別のテーブル(これは、このいずれかに属している)他の多くの行に保存され、
その主キーに関連する多くのオブジェクトを持っています。
- Many to Many
それらの主キーは、両方のテーブルから主キーのペアを保持し、間にテーブルに保存されています。
持っていると多くのオブジェクトに属します。