5
3

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 3 years have passed since last update.

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

Last updated at Posted at 2019-11-15

先日の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を書いておくと安全かもしれない。

5
3
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
5
3

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?