recursiveの 正しい理解CakePHP

至尊电玩 http://www.fspvcpp.c 评论

CakePHPは、データベースのモデルのテーブル設定において、他のテーブル(モデル)に対してアソシエーション(リレーション、連携)の設定をしておけば、当該カレントテーブルの情報を取得するときに、同時に、アソシエーション設定したデータもとってきてく

CakePHPは、データベースのモデルのテーブル設定において、他のテーブル(モデル)に対してアソシエーション(リレーション、連携)の設定をしておけば、当該カレントテーブルの情報を取得するときに、同時に、アソシエーション設定したデータもとってきてくれる。当該カレントモデルのfindAll,findをするだけで、他の連携をとってくれるありがたい機能です。
同時に、recursive というパラメータがあり、再帰的にこのアソシエーションを追っかけてくれる回数を制御するパラメータなのだけど、WEBで検索をすると、かなり混乱しているように見受けられた。(結果オーライの記事が多い)。
なので、ここで、recursiveを正しく使うための基礎知識を若干述べたいな~。
というか自分が理解するために調べたのを覚書として書いておくということだけど。
まず、結論は、図をみていただくのが一番早い。

figure 1(クリックで画面いっぱいに表示します。)

CakePHP_recursive_attention.jpg




結論は図の通りです。

recursive   取得可能な範囲  
-1   カレントテーブルのみ(単体)  
0   カレントテーブル+hasOne,belongsToの第1次アソシエーションテーブル  
1   カレントテーブル+すべてのの第1次アソシエーションテーブル  
2   上記 + subのsub,即ち第2次アソシエーションテーブル  
3以上   上記 + 第3(以上)次のアソシエーションテーブル  

ATTENTTIONの部分を見てください。
ATTENTTION 1 にあるように、hasOneとbelongsToについては、recursive=0 であっても、アソシエーションを追跡します。


hasOne,belongsTo と hasMany は、recursive において異なる挙動をします。


つまり、
「recursive は、アソシエーションの階層を規定するものである」
という理解は間違っていることがわかります。
それが言えるのは、recursive が2以上の時であって、-1 ~ 1 の間は、特別に考えなくてはなりません。

しかし多くの人が間違えて理解しているようです。私自身も最初の頃は、ATTENTTION 1 → ATTENTTION 2 の位置にあるように思っており、大変とまどいました。

おそらくcakePHPのデータ構造に合わせるために、このような仕様にしたのだとは思うのですが、かなり戸惑いますよね。


実は、英語のマニュアルにも(例)が書かれています。
$recursive

This sets the number of levels you wish Cake to fetch associated model data in find() and findAll() operations.

Imagine you have Groups which have many Users which in turn have many Articles.

Model::recursive options $recursive = -1 No associated data is fetched.
$recursive = 0 Cake fetches Group data
$recursive = 1 Cake fetches a Group and its associated Users
$recursive = 2 Cake fetches a Group, its associated Users, and the Users'
associated Articles
CakePHP Manual-Model
若干誤解を生みそうな説明文にとれますが、私が英語に弱いため、正確なところはわかりません。ただ、上記の例は参考になるでしょう。


また、以下のサイトのように recursiv=0 には意味がない!ということにする理解もいいかも知れません。
アソシエーションさせたくない場合の設定方法


なんせ、CakePHP1.2のデフォルトも $this->recursive = 1  ですから。


ソースを読むとわかるのですが、hasOneとbelongsToについては、SQL文にて LEFT JOINして、一度のSQL文の発行で、データを取ってきます。
hasManyとhasAndBelongsToManyについては、一度、カレントテーブルだけのSQL文を発行し、その結果の プライマリーキーを 次の 「in句」 に使用しています。つまり2回のSQL文を発行しています。

このことから、CakePHPは、いわゆる「副問い合わせ(サブクエリー)」については、(自動アソシエーションについては)サポートしていない、と理解できます。たぶんそれは、様々なデータベースに合わせるために仕方がないのでしょう(副問い合わせをサポートしていないデータベースもあるため)。
(追記)これも想像ですが、サポートしていないDBあるというよりも、たぶん、副問い合わせにすると、途中経過のテーブルの情報を抜き出しにくい、ということもあるのかなと思いました。


recursiveがどうしてこのような仕様になったのかは、私にはわかりません。多くの人が単純に考えるように 「recursive=0 で、単体テーブルだけが取得可能」 という仕様のほうが理解しやすいとは思うのですが。。。。。
確かに recursive=0 で、hasOneとbelongsTo を取得するのは、CakePHPの内部プログラムの処理としては、再帰的処理をせず、LEFT JOIN するだけなので、内部的な処理の仕方からの仕様となっていると思います。
内部的にはrecursive変数は、いったん、execute した結果のプライマリーキーを利用して、再帰的に、次のSQL文を作成する、というパラメータになっているのです。hasOne,belongsToは、最初のSQL文で、目的を達成してしまうので、recursive=0でも動作するようになっています。

この仕様の理由の想像 想像でしかないのですが、きっと初期の初期のCakePHPのDBOは、LEFT JOINさえ使わず、hasOne,belongsToにしても、副問い合わせで処理しようとしたのではないでしょうか。
別の理由として考えられるのは、hasOneとbelongsTo だけの追跡をしたい時には、recursive=0 を使えるということかも知れません。

まあ、とにかく hasOne,belognsToの機能は、

SQL文1回のLEFT JOIN

SQL文1回の副問い合わせ

recursiveの 正しい理解CakePHP

公海船票_699彩票:recursiveの 正しい理解CakePHP

喜欢 (0) or 分享 (0)
发表我的评论
取消评论

表情

您的回复是我们的动力!

  • 昵称 (必填)

网友最新评论