基本的なリレーションの設定方法
PhalconでJOINを使いたい時にはModelのinitialize()内で、hasOne,hasMany,belongsToなどを使います。
model/Prefectures.php
public function initialize()
{
// 地方を親に持つのでbelongsTo
$this->belongsTo('region_id', 'Regions', 'id');
// 子に市区町村を持つのでhasMany
$this->hasMany('id', 'Towns', 'prefecture_id');
// 都道府県の詳細は1対1なのでhasOne
$this->hasOne('id', 'PrefectureDetails', 'prefecture_id');
}
ですが、initialize()で実行しているので、JOINしなくてもいい時にも必ずJOINをしてしまい、DBに負荷をかけてしまうのではないかと気になったので調べてみました。
調査開始
findFirstした時とhasMany先を取得する時にどのようなSQLが発行されているか見てみます。
以下ざっくりしたソースです。
調査用ソース
model/Regions.php
class Regions extends \Phalcon\Mvc\Model
{
:
:
public function initialize()
{
$this->hasMany('id', 'Prefectures', 'region_id');
}
}
TestController.php
public function test()
{
$region = Regions::findFirst(1); // ・・・①地方取得
sleep(10); // 確認をしやすくするためにwaitを入れる
$prefectures = $region->prefectures; // ・・・②都道府県取得
}
調査結果
結果として①地方取得で以下のみが実行されました。
(実際はDESCRIBEや、*ではなくカラムが指定されたりしていますが、説明のために端折ってます)
SELECT * FROM regions;
そして②都道府県取得で以下が発行されました。
SELECT * FROM prefectures WHERE region_id=1;
まとめ
リレーションの設定をしたからといって、取得しに行かなければクエリが発行されることはないので、設定して損することはなさそうです。
むしろ、リレーションを明示するために積極的に書くべきだと思います。
ただし、この挙動を理解していないと、データ取得にタイムラグがあるので意図しない結果が返ってくることもあるかもしれません。
ちゃんと JOINして全部取得する方法はPHQLなんですかねー?
そのうち調べておきたいと思います。