Я делаю многопользовательское приложение с несколькими базами данных, в котором есть одна центральная база данных и множество подбатарей.
Приложение создает экземпляр организации в центральной базе данных, и в каждой организации создается суб-база данных с разными таблицами.
Чтобы достичь этого, я создал классную программу Setup
которая
Все завершено в конструкторе, поэтому при Setup::create
все это выполняется правильно.
Большинство настроек и подключения базы данных вдохновляются этим учебным пособием .
Чтобы проверить, идет ли моя логика, как я хотел, я взаимодействовал с моим приложением через:
К моему удивлению, в обоих случаях результат различен и никогда не нужен для связи с другой базой данных.
Взаимодействие с мастером :
После создания вызова моей Setup::create
и вывода, в котором говорится, что все прошло хорошо, я пытаюсь проверить, какая база данных я сейчас использую. Использование:
DB::connection()->getDatabaseName()
Он выводит имя под-базы данных, которое мы только что создали для организации и связанное с ней, что логично и идет соответствующим образом.
Тем не менее, я пытаюсь подключиться к другой базе данных, создав для нее новую конфигурацию, а затем подключившись к ней с помощью методов DB
которые я предоставил, это не работает, я все еще на суббадре, в которой я был.
Взаимодействие с браузером :
На этот раз, когда моя Setup::create
завершена правильно в коде моего контроллера, я снова пытаюсь проверить все, я также сделал строку в своем макете, чтобы вывести мне текущую базу данных:
<?php echo DB::connection()->getDatabaseName() ?>
Сначала, пока я все еще нахожусь в центральной базе данных, появляется его имя, однако после вызова Setup::create
он переключается на под-базу данных – что ожидается – но затем, после одного обновления, я снова попал в центральную базу данных – Что совершенно неожиданно –
Итак, что здесь происходит? и как мне добраться до всех моих разных баз данных, как я хочу, когда захочу?
Дополнительно :
Тестирование во владении, я перешел к точке, где я прокомментировал код миграции, и оставил создание базы данных, а также соединение с ней. К моему удивлению, он не подключается к базе данных. поэтому я начал думать, что код миграции имеет какое-то отношение к подключению к базе данных, или, может быть, возиться с разными поведением, которые я полностью задерживаю.
Важно :
Model::create
после подключения к базе данных вместо DB::connection()->....
Технические характеристики :
Я использую Laravel 5 с mysql-сервером на Ubuntu Machine.
Я наткнулся на этот вопрос, и у меня был мой ответ.
Я создал класс под названием DatabaseConnection
:
class DatabaseConnection extends Model { static $instances=array(); protected $database; protected $connection; public function __construct($options = null) { // Set the database $database = $options['database']; $this->database = $database; // Figure out the driver and get the default configuration for the driver $driver = isset($options['driver']) ? $options['driver'] : Config::get("database.default"); $default = Config::get("database.connections.$driver"); // Loop through our default array and update options if we have non-defaults foreach($default as $item => $value) { $default[$item] = isset($options[$item]) ? $options[$item] : $default[$item]; } $capsule = new Capsule; $capsule->addConnection($default); $capsule->setEventDispatcher(new Dispatcher(new Container)); $capsule->setAsGlobal(); $capsule->bootEloquent(); // Create the connection $this->connection = $capsule->getConnection(); DatabaseConnection::$instances[] = $capsule; return $this->connection; } }
поclass DatabaseConnection extends Model { static $instances=array(); protected $database; protected $connection; public function __construct($options = null) { // Set the database $database = $options['database']; $this->database = $database; // Figure out the driver and get the default configuration for the driver $driver = isset($options['driver']) ? $options['driver'] : Config::get("database.default"); $default = Config::get("database.connections.$driver"); // Loop through our default array and update options if we have non-defaults foreach($default as $item => $value) { $default[$item] = isset($options[$item]) ? $options[$item] : $default[$item]; } $capsule = new Capsule; $capsule->addConnection($default); $capsule->setEventDispatcher(new Dispatcher(new Container)); $capsule->setAsGlobal(); $capsule->bootEloquent(); // Create the connection $this->connection = $capsule->getConnection(); DatabaseConnection::$instances[] = $capsule; return $this->connection; } }
Итак, всякий раз, когда я нахожусь в контроллере, который управляет таблицами суббазы, я просто иду так:
public function RandomActionInMyController() { $db_connection = new DatabaseConnection(['database' => 'name_of_db']); $someModel = new Model/Model::find()..// Basically anything return myreturnstuff; }
Дополнительный бонус :
Использование статического атрибута $instances
в моем DatabaseConnection
сводится к тому, чтобы восстановить мое последнее соединение с базой данных для удобства использования.
Например, если бы я когда-либо хотел получить его, он был бы завернут в функцию, такую как
function CurrentOrLatestDbConnection() { if( !empty(DatabaseConnection::$instances) ) { return end(DatabaseConnection::$instances)->getConnection()->getDatabaseName(); } }
Примечания :
Если вы столкнулись с такими ошибками, как Unknown class 'Container'
или « Capsule
или что-нибудь в этом роде, убедитесь, что вы проверяете ссылку на вопрос, которую я предоставил, и правильно use
утверждения use
.
Что касается предстоящих ответов :
Мне кажется, что это соединение с базой данных живет в скобках действия контроллера, поэтому, когда я перехожу к другому действию, который не указывает на соединение, он автоматически возвращается в центральную базу данных.
Который заставил меня думать, что должен быть способ установить соединение с базой данных с суб-базой «глобальным» способом для всей функции, например, промежуточного программного обеспечения или чего-то еще.
Мне бы хотелось увидеть ответ, воплотив такую вещь.
Обновление :
Я придумал более аккуратный способ сделать это.
Я предполагаю, что вы на том же основании, что и я, желая изменить базы данных условно в соответствии с каждым контроллером … скажем, для каждого из ваших контроллеров требуется другая база данных только ради аргумента.
То, что мы будем использовать для решения этой проблемы, – «Middlewares».
Во-первых, чтобы объяснить, что мы собираемся делать.
Мы собираемся проверить имя контроллера (и даже действие), а затем установить нужную базу данных, которую мы хотим установить.
Перейдите в свою командную строку, введите:
php artisan make:middleware SetDatabaseConnectionMiddleware
Создание промежуточного программного обеспечения с готовым шаблоном.
Или, если вам это нравится, перейдите в свое приложение app_name / app / Http / Middleware и создайте его вручную.
Перейдите в свой файл методов-помощников (если у вас уже есть один, если нет, чувак сделает это!)
function getControllerAndActionName() { $action = app('request')->route()->getAction(); $controller = class_basename($action['controller']); list($controller, $action) = explode('@', $controller); return ['action' => $action, 'controller' => $controller]; }
Это вернет вам массив с именем действия и именем контроллера, если вы хотите ограничить просто имя контроллера, не стесняйтесь удалять 'action' => $action
из кода.
namespace App\Http\Middleware; use Closure; use DatabaseConnection; class SetProperDatabase { /** * Handle an incoming request. * * @param \Illuminate\Http\Request $request * @param \Closure $next * @return mixed */ public function handle($request, Closure $next) { $database_name = ''; $controllerAndActionName = getControllerAndActionName(); $controller_name = $controllerAndActionName['controller']; $action_name = $controllerAndActionName['action']; if($controller_name == 'my_controller_nameController') { $database_name = 'your_proper_database_name'; } else { $database_name = 'other_db'; } $database_connection = new DatabaseConnection(['database' => $database_name']); return $next($request); } }
4. Теперь, что вы правильно создали свое промежуточное ПО, давайте расскажем вашему приложению, где его найти и под каким именем.
В переменной $routeMiddleware
добавьте эту строку
'set_proper_database' => \App\Http\Middleware\SetProperDatabase::class,
Таким образом, мы знаем, как это назвать.
Наконец, настройте его.
Controller.php
(класс Abstract, из которого наследуется все наследование вашего контроллера) public function __construct()
{
$this->middleware('set_proper_database');
}
И это должно сделать это за вас.
Если у вас есть дополнительные вопросы, не стесняйтесь комментировать.
// Ресурсы :
1. Имя контроллера и действия
2. Документация промежуточного программного обеспечения
3. Дальнейшие примечания по документации промежуточного программного обеспечения : я был бы признателен за некоторые издания, касающиеся моего стиля и отступов кода, так как кажется, что я изо всех сил пытался правильно подстроить свой код здесь, но тщетно, у меня не было никаких отступов.