Set connection according to logged user data

Asked

Viewed 246 times

0

I created a second connection in my config/database.php file and I will also create a third one, I wanted to know how to switch between these connections according to the logged in user.

config/database.php

'connections' => [

        'mysql' => [
            'driver' => 'mysql',
            'host' => env('DB_HOST', 'localhost'),
            'port' => env('DB_PORT', '3306'),
            'database' => env('DB_DATABASE', 'forge'),
            'username' => env('DB_USERNAME', 'forge'),
            'password' => env('DB_PASSWORD', ''),
            'charset' => 'utf8',
            'collation' => 'utf8_unicode_ci',
            'prefix' => '',
            'strict' => true,
            'engine' => null,
        ],

        'database2' => [
            'driver' => 'mysql',
            'host' => ('localhost'),
            'port' => ('3306'),
            'database' => ('database2'),
            'username' => ('root'),
            'password' => (''),
            'charset' => 'utf8',
            'collation' => 'utf8_unicode_ci',
            'prefix' => '',
            'strict' => true,
            'engine' => null,
        ],

    ],

I know I can choose the connection in my model this way, but how do I make that name "database2" is pulled from the logged-in user instead of being put the name directly there?

class Empresa extends Model
{
    protected $connection;

    function __construct()
    {
        return $this->connection = 'database2';
    }
}

I tried to put it that way, but it didn’t work.

return $this->connection = Auth::user()->database;

Made that mistake.

Errorexception in Empresa.php line 16:

Trying to get Property of non-object

  • I can have infinite users for each database, that would be unfeasible. And yes, it’s exactly a way to make that call that I need as explained in the question.

  • That’s not it @Shot.

2 answers

1


I noticed that you are trying to access the user data without checking whether it is authenticated or not. You need to define a behavior if the user is not logged in.

The way you did probably gave error because the user is not logged in. If you try to call user data before it is logged in, error will appear Try to get a property of a non-object.

A problem in the Auth of Laravel 5

Another thing is that because Middleware web may not have been executed at the time of the Auth::user(). In that case, if the middleware \Illuminate\Session\Middleware\StartSession::class is not executed (and he is within the group web, the data of Auth::user() will not be loaded as the middleware would be processed after processing the route.

So two things: If you need to process Authentication data elsewhere in the application (as in Service Provider for example), it would be interesting to make the following change:

protected $middleware = [
    \Illuminate\Foundation\Http\Middleware\CheckForMaintenanceMode::class,

    // Pequena alteração. Inicialização de cookies, sessão e erros devem ser incluídos o quanto antes, por contas das requisições que retornam erros

    \Tmt\Http\Middleware\EncryptCookies::class,
    \Illuminate\Cookie\Middleware\AddQueuedCookiesToResponse::class,
    \Illuminate\Session\Middleware\StartSession::class,
    \Illuminate\View\Middleware\ShareErrorsFromSession::class,
];

/**
 * The application's route middleware groups.
 *
 * @var array
 */
protected $middlewareGroups = [
    'web' => [
        // \Tmt\Http\Middleware\EncryptCookies::class,
        // \Illuminate\Cookie\Middleware\AddQueuedCookiesToResponse::class,
        // \Illuminate\Session\Middleware\StartSession::class,
        //\Illuminate\View\Middleware\ShareErrorsFromSession::class,

        \Tmt\Http\Middleware\VerifyCsrfToken::class,
    ],

    'api' => [
        'throttle:60,1',

Solution

The main lesson I would like to explain in this answer is this: it would be interesting to create a Middleware to set the default connection according to the user:

public function handle($request, Closure $next) {

    auth()->check() && config(['database.default' => auth()->user()->database]);

    return $next($request);
}
  • i made the same comment that you about user have to be authenticated, create a middleware will cause problems because the user is part of another connection? will not ?

  • @Virgilionovic I’ve made it very clear that the use of middleware is for a standard connection. If it is going to set a connection for each model, then it will have to do this either in the model or in the controller. Only then you already answered :p

  • it was only a reminder, because, what you did for this particular case, only works once for dynamic connections or do until the fixed configuration in the User model also works. will depend on the user to give us a feedback

  • 1

    I managed to do it with Middleware @Wallacemaxters. I’m still doing some tests, but I think this solution fits my case well

0

The initial logic would be, users (user) would have a configured standard connection. After user authentication create instances of classes who inherit from the Eloquent (os models) as follows:

Controller

namespace App\Http\Controllers;

class CreditosController extends Controller 
{
    private $credito;
    public function __construct()
    {
        // pode fazer injeção pelo construtor também ...
        $this->credito = new App\Models\Creditos(); 

        $this->credito->setConnection(Auth::user()->database);
    }
}

the change in connection that model. The process would be done on Controller, yes and maybe straight, but I wouldn’t recommend.

  • The initial logic is right, but I couldn’t figure out how to implement it. This setConnection is in the controller?

  • @Raylansoares I did an edit, make sure it’s good!

Browser other questions tagged

You are not signed in. Login or sign up in order to post.