Quantcast
Viewing all articles
Browse latest Browse all 331

【Laravel5.8】複数のデータベースに接続するときは全てのモデルに`$connection`を書こう

先日のEagerロード先テーブルは必ず主キーもSELECTしないといけないって記事を見るとわかりますが、Eagerロードでは複数テーブルを結合するのにJOINを使わず、データを別々に取ってきて後から合体させています。

つまり、これは異なるデータベースのテーブルに疑似リレーションを張れるのでは?

テーブルA
class TableA extends Model{
    // テーブル名
    protected $table = 'table_a';

    /**
     * リレーション
     * @return BelongsTo
     */
    public function tableb()
    {
        return $this->belongsTo(TableB::class, 'b_id', 'id');
    }
}
別DBのテーブルB
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を書いておくと安全かもしれない。


Viewing all articles
Browse latest Browse all 331

Trending Articles