マスター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(); } ...メルマガ購読の申し込みはこちらから。