Eloquent Modelのリレーションは動的に変更できる
まさか出来るとは思っていなかったため、せっかくなのでメモ。
概要
リレーションの接続先に当たるテーブルが動的に変化する状態のモデルを、自然にリレーションとして接続したい。
例:
hoge_table
-id
-type
-type_id
-その他ユーザーデータ...
huga_table
-id
-note
-date
hage_table
-id
-note
-date
この時、hoge_table
を示すモデルから、huga_table
とhage_table
のどちらのテーブルと関連しているかを、type
の値をhuga
またはhage
という文字列のどちらが入るかで管理。
type_id
はその時の関連テーブルのid
が代入されている。
実装
Hoge.php
namespace App;
class Hoge extends Model {
protected $table = "hoge_table";
//従来の方式
public function huga() {
return $this->hasOne("App\\Huga", "id", "type_id");
}
public function hage() {
return $this->hasOne("App\\Hage", "id", "type_id");
}
//今回の提案する方式
public function hugaOrHage() {
if ($this->type === "huga") {
return $this->huga();
} else if ($this->type === "hage") {
return $this->hage();
} else {
return null;
}
}
}
Huga.php
class Huga extends Model {
protected $table = "huga_table";
}
Hage.php
class Hage extends Model {
protected $table = "hage_table";
}
このようにリレーションを実装すると、
$hugaOrHageModel = Hoge::find($id)->hugaOrHage;
このように、どちらのリレーションが来るのか意識せずに1つのオブジェクトで呼び出すことが出来るようになる。
ただし、typeにhugaまたはhageが入っていない。つまりnullの値を返す場合は、throwが発生するので注意すること。
また、このように記述したリレーションhugaOrHageに対してEagerロードも出来る。
↑まだ未確認。確認次第追記