我正在使用 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的表格。 为什么?我不知道请更正此代码。
答案 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个以上的登录 ...