Я работаю над приложением, которое является многопользовательской архитектурой с несколькими БД, что в основном означает, что у каждого арендатора есть своя собственная база данных вместо всех арендаторов, живущих в одной БД.
Сейчас я постоянно борюсь с тем, что я не могу успешно изменить соединения с БД, и я не уверен, как правильно это сделать.
Мой файл конфигурации базы данных выглядит так:
'connections' => [
'archive' => [
'driver' => 'mysql',
'host' => env('DB_HOST', 'localhost'),
'database' => env('DB_DATABASE', 'forge'),
'username' => env('DB_USERNAME', 'forge'),
'password' => env('DB_PASSWORD', ''),
'charset' => 'utf8',
'collation' => 'utf8_unicode_ci',
'prefix' => '',
'strict' => false,
],
'tenant' => [
'driver' => 'mysql',
'host' => env('DB_HOST', 'localhost'),
'database' => env('DB_DATABASE', 'forge'),
'username' => env('DB_USERNAME', 'forge'),
'password' => env('DB_PASSWORD', ''),
'charset' => 'utf8',
'collation' => 'utf8_unicode_ci',
'prefix' => '',
'strict' => false,
],
],
Таким образом, основная база данных — это архив, в котором хранится вся информация об арендаторе (компании), и когда пользователь хочет войти в систему, он сначала вводит имя пользователя арендатора (компании), а затем предоставляет свои собственные учетные данные для входа. Таким образом, я знаю, к какой базе данных я должен подключиться и аутентификации пользователя. Если аутентификация прошла успешно, я сохраняю имя пользователя арендатора в сеансе username
переменная, которая в свою очередь используется промежуточным программным обеспечением, которое я написал. Так что в основном, если сессия имеет username
переменная, я знаю, чтобы переключаться на базу данных каждый раз, когда запрос запускается от этого пользователя. Таким образом, я отслеживаю, какой запрос должен соединиться с какой базой данных.
Логика входа в систему:
$this->changeDb($request->input('username'));
$this->saveUsernameToSession($request);
if (\Auth::attempt(['email' => $request->input('email'),
'password' => $request->input('password')])) {
// Authentication passed...
return redirect('/');
}else{
// If the auth atttemp is not successful
// Set default DB as the main one again.
$request->session()->pull('username');
}
Теперь changeDB()
Меня интересует метод, и я не уверен, правильно ли я это делаю.
\Config::set('database.connections.tenant.database', $username);
\Config::set('database.default', 'tenant');
Так что это то, что он делает за кадром. Он в основном изменяет подключение клиента в файле конфигурации базы данных на имя пользователя клиента, поскольку оно совпадает с базой данных клиента. Затем он устанавливает базу данных по умолчанию для подключения клиента.
Это правильный способ разрешения соединения с БД? Или есть другие способы, о которых я не знаю. Возможно, Laravel предоставляет несколько внутренних методов, которые я могу использовать для переключения / разрешения соединений с базой данных.
Вход в систему работает нормально, но меня беспокоит то, что многие другие вещи работают не так хорошо, например, я столкнулся с этой проблемой, пытаясь засадить поддельных арендаторов и засадить их поддельных пользователей.
Я использовал тот же подход, который я использую при входе в систему, но почему-то это не сработало. И хотя ответ предоставил решение моей проблемы, я все еще не уверен, как?
Также я пытался использовать аналогичный подход в методе контроллера для изменения БД, и он не сработал так, как я ожидал снова:
public function showUsersForTenant($id)
{
$tenant = Tenant::findOrFail($id);
\Config::set('database.connections.tenants.database', $tenant->username);
$users = User::on('tenant')->get();
return response()->json($users, 200);
}
Предполагается, что все пользователи определенного арендатора (компании) должны быть возвращены супер-администратору системы, который подключен к основной базе данных. Но он не подключается к базе данных клиентов и продолжает возвращать пользователей из основной БД.
Существуют некоторые пакеты, которые поддерживают многопользовательский подход к работе с несколькими базами данных, но, поскольку я начинающий разработчик, я не могу иметь большого смысла в их репозиториях и в том, как ОНИ меняют / разрешают соединение с БД на лету.
https://github.com/orchestral/tenanti
https://github.com/laraflock/multi-tenant
https://github.com/uxweb/laravel-multi-db
Итак, как успешно изменить / переключить / разрешить соединения в Laravel 5?
В качестве автора второго пакета вы упоминаете (hyn / многопользовательских), Я могу рассказать вам секрет кроется в том, где вы цепляетесь за Laravel.
Предполагая, что вы используете ванильный Laravel, место, где Модели выбирают свое соединение, находится в getConnection()
метод. Отменяя Eloquent Model и используя все ваши модели приложений в этой расширенной модели, вы можете определить, какое соединение использовать «на лету».
Теперь перейдем ко второй проблеме, которая касается сеялок и мигрантов. Это совсем другая история. я вообще-то отменил весь MigrateCommand Laravel поставляется с тем, чтобы оставаться как можно ближе к рабочему методу Laravel. Более простой способ — создать пользовательскую команду, которая устанавливает конфигурацию для конкретного соединения, а затем выполните команду migrate / seed из этой команды с аргументом связи.
Других решений пока нет …