Need to Connect to Multiple Databases in Laravel 10?
You're in the right place!
I'm assuming you already familiar with Laravel 10 basics. If not, no worries, this guide will still be easy to follow.
To start, let's break down the problem and the solution. First up, here's a flowchart to help you visualize the problem:
Laravel comes with a default .env
file, pre-filled with default database credentials like these:
APP_NAME=Laravel APP_ENV=local APP_KEY= APP_DEBUG=true APP_URL=http://localhost ... DB_CONNECTION=mysql DB_HOST=127.0.0.1 DB_PORT=3306 DB_DATABASE=A1 DB_USERNAME=CoolUsernameHere DB_PASSWORD=HotHashedPass ...
By default, Laravel provides the configuration in the .env.example
file. You can remove the .example
suffix to create your .env
file, where you can then customize the settings to match your project's environment.
As shown above, this default configuration is set up for a single database connection.
DB_CONNECTION=mysql DB_HOST=127.0.0.1 DB_PORT=3306 DB_DATABASE=A1 DB_USERNAME=CoolUsernameHere DB_PASSWORD=HotHashedPass
This default configuration connects your project to a single database. If you need to add more connections, then you'll have to write more configurations in your .env
file. For example:
DB_CONNECTION=mysql DB_HOST=127.0.0.1 DB_PORT=3306 DB_DATABASE=A1 DB_USERNAME=CoolUsernameHere DB_PASSWORD=HotHashedPass DB_SECOND_CONNECTION=second_connection DB_SECOND_HOST=127.0.0.1 DB_SECOND_PORT=5528 DB_SECOND_DATABASE=B2 DB_SECOND_USERNAME=HotUsernameHere DB_SECOND_PASSWORD=CoolHashedPass
Next, define your new connection in config/database.php
file:
'second_connection' => [ 'driver' => 'mysql', 'url' => env('DATABASE_URL'), 'host' => env('DB_SECOND_HOST', '127.0.0.1'), 'port' => env('DB_SECOND_PORT', '8809'), 'database' => env('DB_SECOND_DATABASE', 'B2_fallback'), 'username' => env('DB_SECOND_USERNAME', 'ShadowAdmin'), 'password' => env('DB_SECOND_PASSWORD', 'AdminShadow'), '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'), ]) : [], ],
Once you've added the code above, you can continue by registering it in your app/Http/Kernel.php
.
/** * The application's route middleware. * * These middleware may be assigned to groups or used individually. * * @var array<string, class-string|string> */ protected $routeMiddleware = [ 'auth' => \App\Http\Middleware\Authenticate::class, 'auth.basic' => \Illuminate\Auth\Middleware\AuthenticateWithBasicAuth::class, 'cache.headers' => \Illuminate\Http\Middleware\SetCacheHeaders::class, 'can' => \Illuminate\Auth\Middleware\Authorize::class, 'guest' => \App\Http\Middleware\RedirectIfAuthenticated::class, 'password.confirm' => \Illuminate\Auth\Middleware\RequirePassword::class, 'signed' => \Illuminate\Routing\Middleware\ValidateSignature::class, 'throttle' => \Illuminate\Routing\Middleware\ThrottleRequests::class, 'verified' => \Illuminate\Auth\Middleware\EnsureEmailIsVerified::class, // Add this line below 'checkUserLevel' => \App\Http\Middleware\CheckUserLevel::class, ];
Create a new middleware called CheckUserLevel
.
<?php namespace App\Http\Middleware; use Closure; use Illuminate\Http\Request; use Illuminate\Support\Facades\Log; class CheckUserLevel { public function handle(Request $request, Closure $next, $level) { Log::info('CheckUserLevel middleware:', [ 'required_level' => $level, 'user_level' => session('level') ]); if (session('level') < $level) { // If custom credential for user not met, which in this case // we use level as custom credentials for user return redirect('/')->with('error', 'You have no access to this resources'); } return $next($request); } }
In LoginController.php
, you can write custom login logic below.
<?php namespace App\Http\Controllers\Auth; use App\Http\Controllers\Controller; use App\Providers\RouteServiceProvider; use Illuminate\Foundation\Auth\AuthenticatesUsers; use Illuminate\Support\Facades\Auth; use Illuminate\Support\Facades\DB; use Illuminate\Http\Request; use Illuminate\Support\Facades\Hash; use Illuminate\Support\Facades\Log; class LoginController extends Controller { /* |-------------------------------------------------------------------------- | Login Controller |-------------------------------------------------------------------------- | | This controller handles authenticating users for the application and | redirecting them to your home screen. The controller uses a trait | to conveniently provide its functionality to your applications. | */ use AuthenticatesUsers; /** * Override method attemptLogin to include custom login logic. */ protected function attemptLogin(Request $request) { // Step 1: check login with first default database (auth Laravel) if (Auth::attempt($this->credentials($request), $request->filled('remember'))) { return true; } // Step 2: If step 1 fails, then check second database $credentials = $this->credentials($request); $user = DB::connection('second_connection')->table('users') ->where('email', $credentials['email']) ->first(); if ($user && Hash::check($credentials['password'], $user->password)) { // Create custom session if user successfully logged in // with second database credentials $this->createCustomSession($user); // Log user in using taken ID from second database. Auth::loginUsingId($user->id, $request->filled('remember')); return true; } return false; } /** * Handle custom session creation for second database users. */ protected function createCustomSession($user) { // Save user ID and level to session session(['custom_session' => $user->id]); if (isset($user->level)) { session(['level' => $user->level]); } } /** * Override method sendFailedLoginResponse to handle error messages. */ protected function sendFailedLoginResponse(Request $request) { return redirect()->back()->withErrors([ $this->username() => __('auth.failed'), ]); } }
And that's it -- you're all set! 🎉
Now you can use multiple database connections in your project as needed. If you have any questions, don't hesitate to ask! 😊
Top comments (0)