Replicated models and multi-database Eloquent
Concept
Multi-database Eloquent enables connecting different models to different database connections, essential for applications that span multiple databases (read replicas, separate product databases, legacy systems).
Multiple connections: Define connections in config/database.php under the connections array. Each has its own driver, host, database, username, password.
Model-level connection: protected $connection = 'mysql_legacy'. All queries for this model use the named connection.
Model::on('connection'): Run a single query on a specific connection without changing the model's default: User::on('mysql_read')->where('active', true)->get().
DB::connection('name'): Use the Query Builder on a specific connection.
Read/write splitting: The mysql connection in database.php supports read and write sub-arrays. read is an array of servers — Eloquent selects reads (SELECT) from read servers and writes (INSERT/UPDATE/DELETE) to the write server automatically.
Sticky reads: After a write, subsequent reads in the same request go to the write server (to avoid replica lag). Configured with 'sticky' => true in the connection.
Cross-database joins: Only possible between databases on the same server (use database.table notation). Not possible with the Query Builder across different DB hosts.
Code Example
<?php
// config/database.php — multiple connections
'connections' => [
'mysql' => [
'driver' => 'mysql',
'host' => env('DB_HOST', '127.0.0.1'),
'database' => env('DB_DATABASE'),
// read/write splitting:
'read' => [
['host' => env('DB_READ_HOST_1', '127.0.0.1')],
['host' => env('DB_READ_HOST_2', '127.0.0.1')],
],
'write' => [
['host' => env('DB_HOST', '127.0.0.1')],
],
'sticky' => true, // reads after a write go to the write server
],
'analytics' => [
'driver' => 'mysql',
'host' => env('ANALYTICS_DB_HOST'),
'database' => env('ANALYTICS_DB_DATABASE'),
'username' => env('ANALYTICS_DB_USER'),
'password' => env('ANALYTICS_DB_PASS'),
],
'legacy' => [
'driver' => 'mysql',
'host' => env('LEGACY_DB_HOST'),
'database' => env('LEGACY_DB_DATABASE'),
'username' => env('LEGACY_DB_USER'),
'password' => env('LEGACY_DB_PASS'),
],
],
// Model bound to specific connection
namespace App\Models;
class EventLog extends \Illuminate\Database\Eloquent\Model
{
protected $connection = 'analytics';
protected $table = 'event_logs';
public $timestamps = false;
}
class LegacyCustomer extends \Illuminate\Database\Eloquent\Model
{
protected $connection = 'legacy';
protected $table = 'wp_users';
protected $primaryKey = 'ID';
}
// Per-query connection override
$users = User::on('analytics')->where('cohort', '2024')->get();
// Query Builder on named connection
DB::connection('analytics')
->table('page_views')
->where('date', today())
->count();
// Transactions on specific connections
DB::connection('legacy')->transaction(function() {
// operations on legacy DB in a transaction
});
// Cross-DB on same server (different DB, same host)
DB::table('orders')
->join('analytics.page_views as pv', 'orders.session_id', '=', 'pv.session_id')
->select('orders.id', 'pv.referrer')
->get();