先日のEagerロード先テーブルは必ず主キーもSELECTしないといけないって記事を見るとわかりますが、Eagerロードでは複数テーブルを結合するのにJOINを使わず、データを別々に取ってきて後から合体させています。
つまり、これは異なるデータベースのテーブルに疑似リレーションを張れるのでは?
class TableA extends Model{
// テーブル名
protected $table = 'table_a';
/**
* リレーション
* @return BelongsTo
*/
public function tableb()
{
return $this->belongsTo(TableB::class, 'b_id', 'id');
}
}
class TableB extends Model{
// データベースがちがう
protected $connection = 'other_database';
// テーブル名
protected $table = 'table_b';
/**
* リレーション
* @return BelongsTo
*/
public function tablea()
{
return $this->belongsTo(TableA::class, 'a_id', 'id');
}
}
コントローラから呼び出す。
$columnsAB = TableA->with('table_b')->get();
$columnsBA = TableB->with('table_a')->get();
さて、この動作はどうなるでしょうか?
答えは、$columnsAB
は想定通りに取得できる、$columnsBA
は取得できない、です。
わかりづら!
どうしてこんなことになるのでしょうか。
TableA→TableBの順で呼んだ場合、まずデフォルトのDBからTableAを呼び、次いでTableBを見に行った時点でDBが'other_database'に切り替わるのでTableBのデータも正常に取得できる、ということになります。
逆にTableB→TableAの順で呼んだ場合、TableBを見に行った時点でDBが'other_database'に切り替わってTableBのデータを正常に取得し、次いでTableAを見に行きますがDBは'other_database'のままでありTableAが読めない、となります。
原因はTableAに$connection
が書かれていないせいです。
普段$connection
を書いてないときは暗黙的にdefault
が選ばれるので、何も書かずとも問題なく動作します。
しかし一度でも別のデータベースが選ばれると、その後は$connection
を書かないかぎりそのDBが選ばれ続けてしまうみたいです。
まとめ
複数のデータベースに接続する可能性があるときは、デフォルト接続先にも必ず$connection
を書いておくと安全かもしれない。