beta

Laravel・EloquentでDBを変数で動的に切り替える

マルチユーザーサイトやAPIなど、環境やURLによって変数でDBを切り替えたい時があります。Laravel・EloquentでDBを変数で動的に切り替える方法をまとめました。

公開日:2019年3月29日

想定ケース

ユーザーごとにベータベースを切り替えたい、ディレクトリごとに別々のデーターベースで管理したい、という時に、デフォルトのLaravel・Eloquentでは、設定で記述したDBの切り替えは出来ても、動的にDBを切り替えることが出来ません。

今回のケースでは、EloquentのsetConnectionメソッドを動的にし、設定ファイルを都度追加するようにして、モデルをなるべく編集しないで動的にDBを切り替えられるようにします。

実装

コントローラー側

コントローラー側で処理を追加します。コードの例は下記の通りです。

<?php

use SomeModel;

class SomeController extends BaseController {
    public function someMethod()
    {
        $someModel = new SomeModel;
        $someModel->setConnection('DB2');
        $something = $someModel->find(1);
        return $something;
    }
}

Laravel・Eloquent ORMでコントローラー側で接続先DBを動的に切り替える

EloquentのsetConnectionメソッドをコントローラー側から呼び出して、指定のコネクションに切り替えをします。

上記の例ではstaticに書いていますが、someMethodが変数を受ける形にすればアクションごとにDBを切り替えることも可能です。

設定ファイルを分割して、configディレクトリに格納

動的に切り替えるようにできたら、データベースの設定もベタ打ちじゃなくて、動的にするとより便利です。

Laravel・EloquentのDB設定は、config/database.phpに記述する形式になっていますが、そちらを改変してconfig/database/ディレクトリ内の設定ファイルを読み込む形にします。

下記のコードをベースにして、

<?php
$config['database'] = [
    'main' => [
        'driver'    => 'sqlite',
        'database'  => __DIR__ . '/../database/main.sqlite',
    ],
];

// 個別DB設定を全部require
$req_dir = [__DIR__ . '/database/'];
foreach ($req_dir as $r) {
    foreach(glob($r.'*') as $file){
        if(is_file($file)){
            require_once $file;
        }
    }
}

Laravel・Eloquent ORMでデータベース設定ファイルを分割して一気にロードする方法

最後に

return $config['database'];

とすればOKです。

config/database/に格納する設定ファイルは、$config[‘database’]の連想配列になっていればいいので、

<?php
$config['database']['1'] = [
        'driver'    => 'sqlite',
        'database'  => __DIR__ . '/../../database/database.sqlite',
];

とすればOKです。

これで、DBが増えた際には、config/database/内にconfigファイルを追加するだけで、DBの切り替えができるようになります。

EloquentのDB接続設定は、インスタンスが起動した時点ですぐに設定に取り込まれてしまっているので、あとからEloquentに設定を追加していく方法は調べた限りありませんでした。


Laravel・EloquentでDBを変数で動的に切り替える方法を見てきました。

仕組みがわかってしまえば簡単なのですが、Eloquentに関する情報が少なくて、英語の情報をかなり漁ってようやく実装できました。

Laravelの記事にしていますが、ピュアなPHPでも、composerでEloquentを呼び出せば同じことができます。

同じ方法を探している方の参考になれば幸いです。

: