DEV Community

Cover image for Use several databases within your Laravel project
Capsules Codes
Capsules Codes

Posted on • Edited on • Originally published at capsules.codes

Use several databases within your Laravel project

TL;DR: How to use multiple databases within your Laravel project and manage separated records.

 
 

You can find a Laravel Project example on our Github Repository.

 
 

In an effort to maintain clarity for each of my projects, I separate my databases based on the role they play. This blog, for instance, includes several databases: one specifically for the blog and another for analytics. This article explains how to go about it.

 
 

A new Laravel project already contains, in its .env file, information related to the database, including the default mysql connection. We'll be working with two databases: one and two. There will also be a connection to one.

 

.env

Before DB_CONNECTION=mysql DB_HOST=127.0.0.1 DB_PORT=3306 DB_DATABASE=<database-name> DB_USERNAME= DB_PASSWORD= After DB_CONNECTION=one DB_ONE_HOST=127.0.0.1 DB_ONE_PORT=3306 DB_ONE_DATABASE=one DB_ONE_USERNAME= DB_ONE_PASSWORD= DB_TWO_HOST=127.0.0.1 DB_TWO_PORT=3306 DB_TWO_DATABASE=two DB_TWO_USERNAME= DB_TWO_PASSWORD= 
Enter fullscreen mode Exit fullscreen mode

 
 

The default .env file informations is reflected in the database.php configuration file.

 

config/database.php

'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' => 'utf8mb4', 'collation' => 'utf8mb4_unicode_ci', 'prefix' => '', 'prefix_indexes' => true, 'strict' => true, 'engine' => null, 'options' => extension_loaded('pdo_mysql') ? array_filter([ PDO::MYSQL_ATTR_SSL_CA => env('MYSQL_ATTR_SSL_CA'), ]) : [], ], ... ] 
Enter fullscreen mode Exit fullscreen mode

 
 

We'll duplicate this connection information as many times as there are connections.

 
 

'connections' => [ 'one' => [ 'driver' => 'mysql', 'url' => env('DATABASE_URL'), 'host' => env('DB_ONE_HOST', '127.0.0.1'), 'port' => env('DB_ONE_PORT', '3306'), 'database' => env('DB_ONE_DATABASE', 'forge'), 'username' => env('DB_ONE_USERNAME', 'forge'), 'password' => env('DB_ONE_PASSWORD', ''), 'unix_socket' => env('DB_ONE_SOCKET', ''), 'charset' => 'utf8mb4', 'collation' => 'utf8mb4_unicode_ci', 'prefix' => '', 'prefix_indexes' => true, 'strict' => true, 'engine' => null, 'options' => extension_loaded('pdo_mysql') ? array_filter([ PDO::MYSQL_ATTR_SSL_CA => env('MYSQL_ATTR_SSL_CA'), ]) : [], ], 'two' => [ 'driver' => 'mysql', 'url' => env('DATABASE_URL'), 'host' => env('DB_TWO_HOST', '127.0.0.1'), 'port' => env('DB_TWO_PORT', '3306'), 'database' => env('DB_TWO_DATABASE', 'forge'), 'username' => env('DB_TWO_USERNAME', 'forge'), 'password' => env('DB_TWO_PASSWORD', ''), 'unix_socket' => env('DB_TWO_SOCKET', ''), 'charset' => 'utf8mb4', 'collation' => 'utf8mb4_unicode_ci', 'prefix' => '', 'prefix_indexes' => true, 'strict' => true, 'engine' => null, 'options' => extension_loaded('pdo_mysql') ? array_filter([ PDO::MYSQL_ATTR_SSL_CA => env('MYSQL_ATTR_SSL_CA'), ]) : [], ], 
Enter fullscreen mode Exit fullscreen mode

 
 

Then, it is necessary to instruct the migrations to migrate to the different databases created:

one2023_08_31_000000_create_foos_table.php
two2023_08_31_000001_create_bars_table.php

The static function connection('<connection-name>') of the Schema Facade allows for this, which we add in the up() and down() functions.

 
 

2023_08_31_000000_create_foos_table.php

 <?php use Illuminate\Database\Migrations\Migration; use Illuminate\Database\Schema\Blueprint; use Illuminate\Support\Facades\Schema; return new class extends Migration { public function up() : void { Schema::connection( 'one' )->create( 'foos', function( Blueprint $table ) { $table->id(); $table->timestamps(); }); } public function down() : void { Schema::connection( 'one' )->dropIfExists( 'foos' ); } }; 
Enter fullscreen mode Exit fullscreen mode

 
 

2023_08_31_000001_create_bars_table.php

 <?php use Illuminate\Database\Migrations\Migration; use Illuminate\Database\Schema\Blueprint; use Illuminate\Support\Facades\Schema; return new class extends Migration { public function up() : void { Schema::connection( 'two' )->create( 'bars', function( Blueprint $table ) { $table->id(); $table->timestamps(); }); } public function down() : void { Schema::connection( 'two' )->dropIfExists( 'bars' ); } }; 
Enter fullscreen mode Exit fullscreen mode

 
 

Next, the models related to the migrations need to be modified to indicate their connection with the database via the $connection attribute.

 

App\Models\Foo.php

 <?php namespace App\Models; use Illuminate\Database\Eloquent\Model; class Foo extends Model { protected $connection = 'one'; } 
Enter fullscreen mode Exit fullscreen mode

 
 

App\Models\Bar.php

<?php namespace App\Models; use Illuminate\Database\Eloquent\Model; class Bar extends Model { protected $connection = 'two'; } 
Enter fullscreen mode Exit fullscreen mode

 
 

We can now launch the migration php artisan migrate. By default, this command uses the value given by DB_CONNECTION. If it's not defined in the .env file, then it has to be indicated in the command php artisan migrate --database=one.

 
 

In order to test the functionality, we can quickly implement an anonymous function when calling the main route.

 

web.php

<?php use Illuminate\Support\Facades\Route; use App\Models\Foo; use App\Models\Bar; Route::get( '/', function() { $foo = Foo::create(); $bar = Bar::create(); dd( $foo, $bar ); }); 
Enter fullscreen mode Exit fullscreen mode

 
 

The values are then created in the respective databases and visible in the browser.

 
 

In case a database refresh is needed using the command php artisan migrate:fresh, it's worth noting that only the default database, i.e. the one specified by DB_CONNECTION, will be refreshed. Unfortunately, Laravel does not yet support the refreshing of multiple databases at the same time.

 
 

To refresh a database that is not the default one, it is necessary to use the command php artisan db:wipe --database=<database-name>. This command can be repeated for each additional database. Once all databases have been properly wiped with db:wipe, you can then proceed without errors with php artisan migrate:fresh.

 
 

You can also develop your own command that would automate the various tasks needed to clean your database.

 
 

Glad this helped.

 
 

Find out more on Capsules or X

Top comments (0)