如何使用动态数据库进行登录?

时间:2019-03-27 01:28:52

标签: php laravel-5 eloquent

我正在使用 laravel 5.7 进行项目。我必须在其中管理动态数据库的登录名。其中一个主数据库,另一个是子数据库。 因此,当用户提供登录详细信息时,如果未在master上找到登录名,则首先检查master数据库,然后它将在 master_db 上的 App_clients 表上查找电子邮件,并找到该电子邮件ID的数据库名称并检查登录。如果登录成功,则转到仪表板。并且每次登录到子数据库(client_2)之前,数据库都会处于活动状态。

此概念的主要目标是存在两个不同的登录名。

1)登录仅适用于软件所有者的主数据库。 2)另一次登录是针对正在使用此软件的客户端的。

因此,当客户登录时,其数据库名称将使用其电子邮件来自 App_client 表。因此 Laravel Database Config (Laravel数据库配置)将更改并设置新数据库供其使用,并且直到客户端登录后该数据库将处于活动状态,否则默认数据库将处于活动状态。

例如

数据库:: Master_db , Client_2_db , Client_3_db 等。  电子邮件:abc@ex.com和密码:1234存储在Client_2_db中。

首先它将检查Master_db。它会失败。然后电子邮件将显示在 Master_db.App_clients 上,并获取存储在 Master_db.App_clients 上的数据库名称。 因此之后,请尝试从Client_2_db登录。

为此,我正在 myLoginController 上使用此代码。

   if( $request->client == '1111111'  )
    {
        Config::set('database.default', 'mysql');
        DB::reconnect('mysql');
        $loginCheck=  Auth::attempt( ["email" =>$request->username , "password" => $request->password ] );
        if( $loginCheck  )
        {
            // Store Collage ID on session variable.
            $client = SettingClient::where('client_CODE',$request->client_code)->first();
            $request->session()->put('client', $client->ID );
            $request->session()->put('cclient_code', $client->client_CODE );
            $request->session()->put('client_name', $client->client_NAME );
            $request->session()->put('database_name', 'col_master' );
            return redirect('dashboard');
        }
        goto InvalidLoginFound;

    }
    elseif (  $request-> client_code != '1111111'  )
    {
           $clientCheck =  AppClient::where("client_code" , $request->client_code )->orderBy('id','desc')->first();
        if( !$clientCheck   )
        {
            goto clientCodeNotFound ;
        }
        DB::purge('mysql');
        Config::set("database.connections.mysql", [
            "driver" => "mysql",
            "host" => env('DB_HOST'),
            "database" => $clientCheck->database_name,
            "username" => env('DB_USERNAME'),
            "password" => env('DB_PASSWORD'),
            "engine"=>"InnoDB",
        ]);
        Config::set('database.default', 'mysql');
        DB::reconnect('mysql');

        $loginCheck=  Auth::attempt( ["email" =>$request->username , "password" => $request->password ] );
        if( $loginCheck  )
        {
            // Store client ID on session variable.
            $client = SettingClient::where('client_CODE',$request->client_code)->first();
            if( !$client )
            {
                goto clientCodeNotFound;
            }
            $request->session()->put('client', $client->ID );
            $request->session()->put('login_id', $request->username  );
            $request->session()->put('password',  $request->password  );
            $request->session()->put('client_code', $client->client_CODE );
            $request->session()->put('client_name', $client->client_NAME );
            $request->session()->put('database_name', $clientCheck->database_name );
            return redirect('dashboard');
        }

        $request->session()->flush();
        Auth::logout();
        goto InvalidLoginFound;

    }

为此还创建了一个中间件,用于管理每个请求的数据库。

 class DynamicDatabaseMiddleware
{
    /**
     * Handle an incoming request.
     *
     * @param  \Illuminate\Http\Request  $request
     * @param  \Closure  $next
     * @return mixed
     */
    public function handle($request, Closure $next)
    {
        if( session()->get('login_id')  )
        {
            DB::purge('mysql');
            Config::set("database.connections.mysql", [
                "driver" => "mysql",
                "host" => '127.0.0.1',
                "database" => session()->get('database_name')?session()->get('database_name'):'',
                "username" => 'root',
                "password" => '',
                "engine"=>"InnoDB",
            ]);
           // Config::set('database.default', 'mysql');
            DB::reconnect('mysql');


        }
        return $next($request);
    }
}

在Karnel.php上

protected $middlewareGroups = [
    'web' => [
        \App\Http\Middleware\EncryptCookies::class,
        \Illuminate\Cookie\Middleware\AddQueuedCookiesToResponse::class,
        \Illuminate\Session\Middleware\StartSession::class,
        // \Illuminate\Session\Middleware\AuthenticateSession::class,
        \Illuminate\View\Middleware\ShareErrorsFromSession::class,
        \App\Http\Middleware\VerifyCsrfToken::class,
        \Illuminate\Routing\Middleware\SubstituteBindings::class,
        \App\Http\Middleware\SessionDataMiddleware::class,
        \App\Http\Middleware\StoreExceptionMiddleware::class,


        \App\Http\Middleware\DynamicDatabaseMiddleware::class, 
    ],

这是可行的,但是问题是当我尝试检查登录 Auth :: user()时,我总是从 Master_db(col_master)获取登录详细信息来自client_db的表格。 为什么?我不知道请更正此代码。

2 个答案:

答案 0 :(得分:0)

您在正确的道路上。只是还没有。

您需要在中间件中添加整个登录请求,并且对于要检查的每个数据库连接,都放置一个switch或try / catch(使用-> Continue)或if / elseif语句以抛出evry数据库连接,并且如果在其中的一个中找到了该用户,则它将连接他并转到下一个请求,否则将显示错误。注意,在您的语句(数据库连接开关)中,您需要清除连接并再次连接到新的数据库用户名/密码。您可以使用(

        DB::purge('mysql');

 config(['database.connection.mysql' => 
'driver' => 'mysql',
'host' => ''.
'database' =>,
etc.....
]));
        DB::reconnect('mysql');
        Schema::connection('mysql')->getConnection()->reconnect();

祝你好运

答案 1 :(得分:0)

我进行了很多搜索并尝试了许多解决方案,但在我这个时代,没有任何解决方案起作用。 现在我可以回答我的问题了。

我只是做一个函数来搜索 .ENV 文件中的DB_NAME,然后替换它。 找到我的客户登录数据库后,它将在.ENV上用新数据库替换旧数据库名称。 登录后,再次在注销时替换默认数据库名称。

   protected function updateEnv($key, $newValue, $separator='')
    {

        $path = base_path('.env');
        // get old value from current env
        $oldValue = env($key);

        // was there any change?
        if ($oldValue === $newValue) {
            return;
        }

        // rewrite file content with changed data
        if (file_exists($path)) {
            // replace current value with new value
            return  file_put_contents(
                $path, str_replace(
                    $key.'='.$separator.$oldValue.$separator,
                    $key.'='.$separator.$newValue.$separator,
                     file_get_contents($path)
                )
            );
        }
    }

//用于登录

  $this->updateEnv('DB_DATABASE',$appClient->db_name,'');

但仍然是一个问题。它第一次返回null,然后再次刷新就可以了。我不知道。

此解决方案不适用于来自不同位置的1个以上的登录 ...