LaravelでモデルごとにDB接続先を切り替える方法
生徒
「Laravelで、あるモデルだけ別のデータベースに接続したい場合はどうすればいいですか?」
先生
「Laravelでは、モデルごとに接続するデータベースを指定することができます。$connectionプロパティを使う方法です。」
生徒
「$connectionプロパティって何ですか?」
先生
「モデルがどのデータベース接続を使うかを指定する変数です。これにより、アプリ全体でなく特定のモデルだけ別のDBを使えます。」
生徒
「具体的な例を見せてもらえますか?」
先生
「もちろんです。それでは順を追って説明しましょう。」
1. データベース接続を設定する
Laravelで複数のデータベースを扱うための第一歩は、接続情報を定義することです。まずは設定ファイルである config/database.php を開きましょう。このファイルは、アプリケーションがどのサーバーの、どのデータベースに接続するかを管理する「住所録」のような役割を果たします。
例えば、メインのデータベース(mysql)とは別に、外部システム用のデータベース(secondary)を追加したい場合は、以下のように connections 配列の中に新しい設定を追記します。
'connections' => [
// デフォルトのメイン接続(例:ユーザー情報など)
'mysql' => [
'driver' => 'mysql',
'host' => env('DB_HOST', '127.0.0.1'),
'port' => env('DB_PORT', '3306'),
'database' => env('DB_DATABASE', 'laravel_main'),
'username' => env('DB_USERNAME', 'root'),
'password' => env('DB_PASSWORD', ''),
'charset' => 'utf8mb4',
'collation' => 'utf8mb4_unicode_ci',
'prefix' => '',
'strict' => true,
'engine' => null,
],
// 2つ目の接続先(例:注文履歴データ専用DBなど)
'secondary' => [
'driver' => 'mysql',
'host' => env('DB_SECOND_HOST', '127.0.0.1'),
'port' => env('DB_SECOND_PORT', '3306'),
'database' => env('DB_SECOND_DATABASE', 'order_history_db'),
'username' => env('DB_SECOND_USERNAME', 'root'),
'password' => env('DB_SECOND_PASSWORD', ''),
'charset' => 'utf8mb4',
'collation' => 'utf8mb4_unicode_ci',
'prefix' => '',
'strict' => true,
'engine' => null,
],
],
設定時のポイントは、env() 関数を使っている箇所です。これは .env ファイルに記述された値を読み込む仕組みです。実際の開発では、以下のように .env ファイルにも接続情報を追記しましょう。これにより、本番環境と開発環境でスムーズに設定を切り替えられます。
# メインDBの設定
DB_CONNECTION=mysql
DB_HOST=127.0.0.1
DB_DATABASE=laravel_main
# サブDB(secondary)の設定
DB_SECOND_HOST=127.0.0.1
DB_SECOND_DATABASE=order_history_db
このように 'secondary' という名前(キー)で接続先を定義しておくことで、後ほど作成するモデルから「このモデルは secondary を使う」と指名できるようになります。プログラミング初心者の方は、まず「名前をつけて接続先を増やす」という感覚で覚えておけば大丈夫です。
2. モデルごとに接続先を切り替える
モデルで別の接続を使うには、$connectionプロパティを設定します。
namespace App\Models;
use Illuminate\Database\Eloquent\Model;
class Order extends Model
{
// secondary接続を使用
protected $connection = 'secondary';
protected $table = 'orders';
}
このOrderモデルを使ってクエリを実行すると、自動的にsecondary接続先のデータベースが使われます。
3. 接続先を動的に切り替える方法
場合によっては、実行時に接続先を変えたいことがあります。その場合は、setConnectionメソッドを使います。
$order = new Order();
$order->setConnection('mysql'); // デフォルト接続に切り替え
$orders = $order->all();
これにより、モデルインスタンス単位で接続先を切り替えられます。
4. 注意点とポイント
モデルごとの接続切り替えは便利ですが、注意点もあります。
- リレーションで異なる接続を使う場合、Eager LoadingやJoinで想定外の動作になることがある。
- トランザクションは接続ごとに管理されるため、複数接続での一貫性には注意。
- キャッシュやイベントも接続ごとに動作する場合があるので確認が必要。
これらを理解しておくと、モデルごとのデータベース切り替えを安全に行えます。
5. まとめ
Laravelでは$connectionプロパティやsetConnectionメソッドを使うことで、モデルごとにデータベース接続を切り替えることが可能です。これにより、複数のデータベースを扱うアプリケーションでも柔軟にデータ操作ができます。
まとめ
ここまで、Laravelにおけるデータベース接続の柔軟な切り替え方法について詳しく解説してきました。大規模なシステム開発や、外部システムとのデータ連携が必要なプロジェクトにおいて、複数のデータベースを使い分ける技術は非常に重要です。単一のデータベースだけでなく、用途に応じて最適なストレージを選択し、それをLaravelのEloquentモデルという強力な武器で制御できる点は、このフレームワークの大きな魅力と言えるでしょう。
データベース接続管理の重要性
現代のウェブアプリケーション開発では、読み取り専用のレプリカデータベースを利用した負荷分散や、ログ専用のデータベース、あるいは特定の基幹システムが管理するデータベースへの直接アクセスなど、マルチデータベース構成が求められる場面が多々あります。Laravelの「設定より規約」という思想に基づけば、config/database.php に定義を追加し、モデルに一行書き足すだけでこの複雑な制御が実現できるのです。
実践的なコード例:複数の接続先を持つモデルの定義
改めて、実際の開発現場でよく使われるモデルの実装パターンをおさらいしておきましょう。例えば、ユーザー情報はメインのデータベースに保存し、注文履歴などの膨大なデータは別のサブデータベースで管理するといった設計が考えられます。
namespace App\Models;
use Illuminate\Database\Eloquent\Model;
/**
* 注文履歴モデル(サブデータベース接続用)
* * 大規模データの処理効率を考慮し、メインDBとは別の
* 'order_db'接続を利用するように設定しています。
*/
class OrderHistory extends Model
{
// config/database.phpで定義した接続名を指定
protected $connection = 'order_db';
// テーブル名の明示的な指定(必要に応じて)
protected $table = 'order_histories';
// 一括代入可能な属性
protected $fillable = [
'user_id',
'product_id',
'amount',
'ordered_at',
];
}
実行時に動的に接続先を制御する高度なテクニック
静的にプロパティで指定するだけでなく、ユーザーの属性や特定の条件によって接続先を切り替えたい、という要望も少なくありません。その場合は、インスタンス化の際に on() メソッドを使用するか、取得済みのインスタンスに対して setConnection() を実行します。
// 特定の接続先を指定してデータを取得する例
$specificOrders = OrderHistory::on('archive_db')->where('year', 2023)->get();
// 保存時に接続先を切り替える例
$log = new \App\Models\SystemLog();
$log->setConnection('log_server');
$log->message = 'システムエラーが発生しました。';
$log->save();
実行結果として、Laravel内部のクエリログを確認すると、指定した接続設定に基づいてSQLが発行されていることが分かります。
// log_server 接続での実行イメージ
[2026-01-30 12:00:00] local.INFO: insert into `system_logs` (`message`, `updated_at`, `created_at`) values ('システムエラーが発生しました。', '2026-01-30 12:00:00', '2026-01-30 12:00:00')
マイグレーションにおける注意点
モデルの接続先を変えるだけでは不十分です。テーブルを作成するマイグレーションファイルでも、どの接続先に対してテーブルを作るかを明示する必要があります。これを忘れると、デフォルトのデータベースにテーブルが作成されてしまい、実行時に「テーブルが見つかりません」というエラーに悩まされることになります。
use Illuminate\Database\Migrations\Migration;
use Illuminate\Support\Facades\Schema;
class CreateOrderHistoriesTable extends Migration
{
/**
* マイグレーションの実行
*/
public function up()
{
// 接続先を明示的に指定してスキーマを操作する
Schema::connection('order_db')->create('order_histories', function ($table) {
$table->id();
$table->foreignId('user_id');
$table->integer('amount');
$table->timestamps();
});
}
/**
* マイグレーションの切り戻し
*/
public function down()
{
Schema::connection('order_db')->dropIfExists('order_histories');
}
}
複数DB運用の際のベストプラクティス
複数のデータベースを跨ぐ処理を行う場合、最も注意すべきは「トランザクション」の整合性です。Laravelの DB::transaction はデフォルトでは一つの接続しか保護しません。複数の接続を同時にトランザクションに含めるには、それぞれの接続に対してトランザクションを開始し、慎重にコミットやロールバックを制御する必要があります。
また、異なるデータベースにあるテーブル同士をEloquentの join で結合することは基本的にはできません。これはLaravelの制約というより、SQLサーバー側の制約です(同じサーバー内の別スキーマであれば可能な場合もあります)。そのため、リレーションを活用して「Eager Loading」を行うなど、アプリケーション側でデータをマージする設計が推奨されます。
生徒
「先生、まとめまで読んで、マルチデータベースの使い方がかなりクリアになりました!基本は $connection をモデルに書くだけでいいんですね。」
先生
「その通りです。意外とシンプルだったでしょう?でも、ただ設定するだけじゃなくて、マイグレーションファイルでも Schema::connection() を使って接続先を教えないといけない点は忘れがちなポイントだよ。」
生徒
「確かに。モデルだけ変えても、データベース側にテーブルがなければ動かないですもんね。もし、10個くらいデータベースがあったとしても、この方法で管理できるんですか?」
先生
「技術的には可能だよ。ただ、接続先が増えるほど、それぞれの接続が生きているか、パフォーマンスが落ちていないかといった運用コストも増えるから、設計段階で本当にデータベースを分ける必要があるかは検討が必要だね。」
生徒
「なるほど。あと、トランザクションの話が少し難しかったです。別のDB同士だと一気にキャンセルするのが大変ってことですよね?」
先生
「いいところに気づいたね。片方のDBの書き込みは成功したのに、もう片方のDBでエラーが出て失敗した場合、データの不整合が起きてしまうんだ。だから、基本的には『強い整合性』が必要なデータは同じデータベースにまとめるのがセオリーだよ。」
生徒
「勉強になります!まずは安全な範囲で、ログの保存先を分けるところから実践してみようと思います。ありがとうございました!」
先生
「素晴らしいね。まずは手を動かして、エラーが出る感覚を掴むのが一番の近道だよ。頑張ってね!」