先日Laravel案件で、目的によって複数DBを使い分けるシステムを構築したのだが、その時にハマったことなどを備忘録としてまとめておく。

DB接続情報の定義

まず、複数のDBを使用するにあたり、それぞれのDBの接続情報を.envファイルに記述する。
※今回は二つのPostgreSQLに接続する例を紹介する。

# デフォルトDB
DB_CONNECTION=db01
DB_HOST=xxx.xxx.xxx.xxx
DB_PORT=xxxx
DB_DATABASE=xxxx
DB_USERNAME=xxxx
DB_PASSWORD=xxxx

# 二つ目のDB
DB_CONNECTION_02=db02
DB_HOST_02=xxx.xxx.xxx.xxx
DB_PORT_02=xxxx
DB_DATABASE_02=xxxx
DB_USERNAME_02=xxxx
DB_PASSWORD_02=xxxx

次にconfig/database.phpconnectionsにも接続情報を追記する。

<?php

use Illuminate\Support\Str;

return [
    'default' => env('DB_CONNECTION', 'mysql'),

    'connections' => [
        // ...

        'db01' => [
            'driver' => 'pgsql',
            'url' => env('DATABASE_URL'),
            'host' => env('DB_HOST', '127.0.0.1'),
            'port' => env('DB_PORT', '5432'),
            'database' => env('DB_DATABASE', 'forge'),
            'username' => env('DB_USERNAME', 'forge'),
            'password' => env('DB_PASSWORD', ''),
            'charset' => 'utf8',
            'prefix' => '',
            'prefix_indexes' => true,
            'search_path' => 'public',
            'sslmode' => 'prefer',
        ],

        'db02' => [
            'driver' => 'pgsql',
            'url' => env('DATABASE_URL'),
            'host' => env('DB_HOST_02', '127.0.0.1'),
            'port' => env('DB_PORT_02', '5432'),
            'database' => env('DB_DATABASE_02', 'forge'),
            'username' => env('DB_USERNAME_02', 'forge'),
            'password' => env('DB_PASSWORD_02', ''),
            'charset' => 'utf8',
            'prefix' => '',
            'prefix_indexes' => true,
            'search_path' => 'public',
            'sslmode' => 'prefer',
        ],
    ],
];

コードを少し解説すると、defaultDB_CONNECTIONが指定されているが、これは.envファイルで定義したdb01をデフォルトの接続先とすることを意味している。

マイグレーション時のDB接続先を変更する

マイグレーションする際、何もしないと前述のdefaultで指定したDBに対して操作がおこなわれてしまうので、接続先を変更するため以下の記述が必要となる。

<?php

use Illuminate\Database\Migrations\Migration;
use Illuminate\Database\Schema\Blueprint;
use Illuminate\Support\Facades\Schema;

return new class extends Migration
{
    protected $connection = 'db02'; // 追記
    
    /**
     * Run the migrations.
     *
     * @return void
     */
    public function up()
    {
        // ...

これでマイグレーションを実行すると、db02として定義したDBに対してマイグレーション操作がおこなわれるようになる。

モデルファイルの接続設定

接続先DBが変わるので、当然モデルファイルでも接続設定をおこなわなければならない。

<?php

namespace App\Models;

use Illuminate\Database\Eloquent\Factories\HasFactory;
use Illuminate\Database\Eloquent\Model;

class Product extends Model
{
    use HasFactory;

    /** @var string DB接続設定 */
    protected $connection = 'db02';

    // ...

接続設定の書き方はマイグレーションファイルと同様、$connectionで接続先を指定する。

なお注意点として、モデル間でリレーションを取る場合(hasManyなど)にそれぞれのモデルが参照するテーブルが属するDBが異なるとエラーとなってしまうので、モデルの接続設定はデフォルトDBを使う場合でも以下のように接続先を明示しておく必要がある。

<?php

namespace App\Models;

use Illuminate\Database\Eloquent\Factories\HasFactory;
use Illuminate\Database\Eloquent\Model;

class ProductMaster extends Model
{
    use HasFactory;

    /** @var string DB接続設定 */
    protected $connection = 'db01';

    // ...

複数のDBを使用する場合は、とりあえず全モデルファイルで接続設定を記述しておく方が無難だろう。