マスターDBの変更が複製DBに反映されるまでの時間差を考えると、サイトの特定のページでは複製DBのアクセスを使用したくないかもしれません。例えば、会員のログインなど会員のアカウントの情報に関わるページとか、Eコマースのチェックアウトのページとか、あるいは管理者のみがアクセスする管理ページとか。そうなると、特定のコントローラだけに複製DBコネクションを限定するにはどのようにすればよいのでしょう?

まず、マスターDBのみのDBコネクションをmysqlとして、複製DBを使用するDBコネクションをmysql_rwとして、config/database.phpで2つのコネクションを設定します。


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

    'connections' => [

        'mysql' => [
            'driver' => 'mysql',
            'url' => env('DATABASE_URL'),
            'host' => env('DB_HOST', '127.0.0.1'),
            'port' => env('DB_PORT', '3306'),
            'database' => env('DB_DATABASE', 'forge'),
            'username' => env('DB_USERNAME', 'forge'),
            'password' => env('DB_PASSWORD', ''),
            'unix_socket' => env('DB_SOCKET', ''),
            'charset' => 'utf8',
            'collation' => 'utf8_unicode_ci',
            'prefix' => '',
            'strict' => false,
            'engine' => null,
            'timezone' => 'Asia/Tokyo',
        ],

        'mysql_rw' => [
            'driver' => 'mysql',
            'url' => env('DATABASE_URL'),
            'read' => [
                'host' => env('DB_HOST_RO', env('DB_HOST', '127.0.0.1')),
                'username' => env('DB_USERNAME_RO', env('DB_USERNAME')),
                'password' => env('DB_PASSWORD_RO', env('DB_PASSWORD')),
            ],
            'write' => [
                'host' => env('DB_HOST', '127.0.0.1'),
                'username' => env('DB_USERNAME', 'forge'),
                'password' => env('DB_PASSWORD', ''),
            ],
            'port' => env('DB_PORT', '3306'),
            'database' => env('DB_DATABASE'),
            'unix_socket' => env('DB_SOCKET', ''),
            'charset' => 'utf8',
            'collation' => 'utf8_unicode_ci',
            'prefix' => '',
            'strict' => false,
            'engine' => null,
            'timezone' => 'Asia/Tokyo',
        ],
..

.envのファイルでは、DB_HOST_RO, DB_USERNAME_RO, DB_PASSWORD_ROの設定項目の指定が必要となります。
ROはRead Onlyという意味で読み込み専用のユーザーが複製DBにアクセスします。

また、デフォルトは、マスターDBのコネクションであることに注意してください。

次に、例えば、商品閲覧ページにおいてDBコネクションを変えるには、以下のように、コントローラのコンストラクタにおいて、コネクションのデフォルトを上書きしてDB::reconnect()で接続します。


namespace App\Http\Controllers;

class ProductController extends Controller
{
    public function __construct()
    {
        parent::__construct();

        config(['database.default' => 'mysql_rw']);
        DB::reconnect();
..

簡単ですね。

いちいち、それぞれのコンストラクタでコネクションを変えるのが面倒なら、以下のよう親のコントローラにおいてまとめて指定することも可能です。試してはいないですが、ミドルウェアでの対応も可能なはずです。

    public function __construct()
    {
        $route = Route::currentRouteName();

        // 特定のページだけDBコネクションを変更する
        $routes = [
            'user.home',
            'user.page',
            'user.shop',
            'user.category',
            'user.collection',
            'user.product',
        ];

        if (in_array($route, $routes)) {
            config(['database.default' => 'mysql_rw']);
            DB::reconnect();
        }
...

By khino