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