Reputation: 319
In config/database.php
I have two connections: mysql
and website
. Both connect to the same host, just the database is different. The default is mysql
.
I have created a middleware called SetupWebsite
which checks if the incoming domain exists in the database in the default connection. If it does, it fills the website
connection with the correct database with the following code:
config(['database.connections.website.database' => $database]);
Then, it switches the default connection to website
:
config(['database.default' => 'website']);
I verified that the default connection is now website
by retrieving a value from the database which only exists in the website
connection. I can also login to a user account in the website
connection. Now, when I set the following route:
Route::get('admin', function () {
return 'Welcome to the dashboard!';
})->middleware('auth');
And I go there after a successful login, I get the error message that 'tbl_users does not exists' and I see it uses the mysql
connection to check if the user is authenticated. I ran out of ideas how to tell Laravel that I'm using another database connection. FIY: I didn't cache the configuration.
When I add the following code to the constructor of Illuminate\Auth\Middleware\Authenticate::class
:
DB::setDefaultConnection('website');
I get the error message that no database is selected, which means that the auth middleware is 'created' before my SetupWebsite
middleware does its magic. Any suggestions how I can fix this?
Upvotes: 3
Views: 2256
Reputation: 134
For other people finding this, I ran into the same problem with Laravel Passport and multi-tenancy. I've got a general database too, with another database per tenant. There's an easier solution, than copying the auth middleware above. Just use the middleware priorities of Laravel.
In Kernel.php
, you've got the property $middlewarePriority
, just add your database changing middleware before the authentication middleware of Laravel.
/**
* The priority-sorted list of middleware.
*
* This forces non-global middleware to always be in the given order.
*
* @var array
*/
protected $middlewarePriority = [
\Illuminate\Session\Middleware\StartSession::class,
\Illuminate\View\Middleware\ShareErrorsFromSession::class,
// Always connect to the DB first, before executing AUTH middleware
\App\Http\Middleware\ConnectToDatabase::class,
\App\Http\Middleware\Authenticate::class,
\Illuminate\Session\Middleware\AuthenticateSession::class,
\Illuminate\Routing\Middleware\SubstituteBindings::class,
\Illuminate\Auth\Middleware\Authorize::class,
];
Upvotes: 1
Reputation: 319
Whoop! I found a workaround for this. Like I said in my question, it looks like the auth middleware is setup before my own middlewares are, which results in the auth middleware using the default connection known on startup, which is mysql
. So I decided to copy-paste the auth middleware to a new middleware called something like AwesomeAuthMiddleware
and use that one instead. That worked!
Upvotes: 2