Mysql
 sql >> Base de Dados >  >> RDS >> Mysql

Como me conecto a diferentes bancos de dados em tempo de execução?


Me deparei com esta pergunta e teve minha resposta.

Eu fiz uma classe chamada 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;
        }
}

Então, sempre que estou em um controller que manipula tabelas de um sub-banco de dados, simplesmente faço assim:
public function RandomActionInMyController()
{
      $db_connection = new DatabaseConnection(['database' => 'name_of_db']);
       $someModel = new Model/Model::find()..// Basically anything
        return myreturnstuff;
}

Bônus Extra :

O uso do atributo estático $instances no meu DatabaseConnection se resume a recuperar minha conexão de banco de dados mais recente para facilitar o uso.

Por exemplo, se eu quisesse recuperá-lo, ele seria envolvido em uma função como
function CurrentOrLatestDbConnection()
{
    if( !empty(DatabaseConnection::$instances) )
    {
        return end(DatabaseConnection::$instances)->getConnection()->getDatabaseName();
    }
}

Observações :

Se você encontrar erros como Unknown class 'Container' ou Capsule ou qualquer coisa desse tipo, verifique o link da pergunta que forneci e use use declarações corretamente.

Em relação às próximas respostas :

Parece-me que esta conexão de banco de dados vive entre os colchetes da ação do controlador, então quando eu prossigo para outra ação que não especifica nenhuma conexão, ela retorna ao banco de dados central automaticamente.

O que me fez pensar que deve haver uma maneira de definir a conexão do banco de dados com o sub-banco de dados de uma maneira 'global' para toda a função, como um middleware ou algo assim.

Eu adoraria ver uma resposta, implementando tal coisa.

Atualizar :

Eu inventei uma maneira mais legal de fazer isso.

Suponho que você esteja no mesmo terreno que eu, desejando alterar os bancos de dados condicionalmente de acordo com cada controlador ... digamos, cada um dos seus controladores requer um banco de dados diferente, apenas por causa do argumento.

O que usaremos para resolver isso é `Middlewares.

Primeiro, para explicar o que estamos prestes a fazer.

Vamos verificar o nome do controlador (e até mesmo a ação) e, em seguida, definir o banco de dados adequado que desejamos definir.

  1. Vá para sua linha de comando, digite:

    php artisan make:middleware SetDatabaseConnectionMiddleware

Para criar um middleware com clichê pronto.

Ou, se você gosta da maneira mais difícil, vá para seu app_name/app/Http/Middleware e crie um manualmente.

  1. Vá para o seu arquivo de métodos auxiliares (se você já tiver um, se não, cara, faça um!)
     function getControllerAndActionName()
    {
    
    $action = app('request')->route()->getAction();
    
    $controller = class_basename($action['controller']);
    
    list($controller, $action) = explode('@', $controller);
    
    return ['action' => $action, 'controller' => $controller];
    }
    

Isso retornará para você um array com o nome da ação e o nome do controlador, se você quiser retornar de forma restrita apenas o nome do controlador, sinta-se à vontade para remover 'action' => $action do código.
  1. Dentro do seu middleware, ele ficará assim:


    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. Agora que você criou corretamente seu middleware, deixe-nos dizer ao seu aplicativo onde encontrá-lo e com que nome.
  1. Vá para seu app_name/app/Http/Kernel.php

  2. Em seu $routeMiddleware variável, adicione esta linha

    'set_proper_database' => \App\Http\Middleware\SetProperDatabase::class,

Desta forma, sabemos como chamá-lo.

  1. Finalmente, configurando-o.
    1. Vá para seu Controller.php (a classe abstrata da qual todos os seus controladores herdam)

    public function __construct() { $this->middleware('set_proper_database'); }

E isso deve fazer isso por você.

Se você tiver mais alguma dúvida, sinta-se à vontade para comentar.

// Recursos :

1.Nome do controlador e da ação

2.Documentação de middleware

3.Outra documentação de middleware Observações :Agradeceria alguma edição sobre meu estilo e recuo de código, pois parece que lutei para estilizar meu código corretamente aqui, mas em vão, os recuos que usei não tiveram efeito.