sql >> Base de Datos >  >> RDS >> Mysql

¿Cómo me conecto a diferentes bases de datos en tiempo de ejecución?

Me topé con esta pregunta y tenía mi respuesta.

Hice una clase llamada 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;
        }
}

Entonces, cada vez que estoy en un controlador que manipula tablas de una subbase de datos, simplemente hago lo siguiente:

public function RandomActionInMyController()
{
      $db_connection = new DatabaseConnection(['database' => 'name_of_db']);
       $someModel = new Model/Model::find()..// Basically anything
        return myreturnstuff;
}

Bonificación adicional :

El uso del atributo estático $instances en mi DatabaseConnection se reduce a recuperar mi última conexión a la base de datos para facilitar los usos.

Por ejemplo, si alguna vez quisiera recuperarlo, estaría envuelto en una función como

function CurrentOrLatestDbConnection()
{
    if( !empty(DatabaseConnection::$instances) )
    {
        return end(DatabaseConnection::$instances)->getConnection()->getDatabaseName();
    }
}

Notas :

Si encuentra errores como Unknown class 'Container' o Capsule o algo por el estilo, asegúrese de revisar el enlace de la pregunta que he proporcionado y use use declaraciones correctamente.

Sobre las próximas respuestas :

Me parece que esta conexión a la base de datos vive dentro de los corchetes de la acción del controlador, por lo que cuando procedo a otra acción que especifica que no hay conexión, vuelve a la base de datos central automáticamente.

Lo que me hizo pensar que debe haber una manera de establecer la conexión de la base de datos a la base de datos secundaria de una manera 'global' para toda la función, como un middleware o algo así.

Me encantaría ver una respuesta, implementando tal cosa.

Actualizar :

Se me ocurrió una forma más ordenada de hacerlo.

Supongo que está en el mismo terreno que yo, queriendo cambiar las bases de datos condicionalmente de acuerdo con cada controlador... digamos, cada uno de sus controladores requiere una base de datos diferente, solo por el bien del argumento.

Lo que usaremos para resolver esto es `Middlewares.

Primero, explicar lo que estamos a punto de hacer..

Vamos a verificar el nombre del controlador (e incluso la acción) y luego configuraremos la base de datos adecuada que deseamos configurar.

  1. Vaya a su línea de comandos, escriba:

    php artisan make:middleware SetDatabaseConnectionMiddleware

Para crear un middleware con repetitivo listo.

O, si le gusta de la manera difícil, vaya a su app_name/app/Http/Middleware y cree uno manualmente.

  1. Ve a tu archivo de métodos auxiliares (si ya tienes uno, si no, ¡haz uno!)

     function getControllerAndActionName()
    {
    
    $action = app('request')->route()->getAction();
    
    $controller = class_basename($action['controller']);
    
    list($controller, $action) = explode('@', $controller);
    
    return ['action' => $action, 'controller' => $controller];
    }
    

Esto le devolverá una matriz con el nombre de la acción y el nombre del controlador, si desea devolver de forma restringida solo el nombre del controlador, siéntase libre de eliminar 'action' => $action del código.

  1. Dentro de su middleware, se verá de esta manera:

    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.Ahora que ha creado correctamente su middleware, permítanos decirle a su aplicación dónde encontrarlo y con qué nombre.

  1. Ve a tu app_name/app/Http/Kernel.php
  2. En su $routeMiddleware variable, agregue esta línea

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

Así sabemos cómo llamarlo.

  1. Finalmente, configurarlo.

    1. Ve a tu Controller.php (la clase abstracta de la que heredan todos los controladores)

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

Y esto debería hacerlo por ti.

Si tiene más preguntas, no dude en comentar.

// Recursos :

1.Nombre del controlador y de la acción

2.Documentación de middleware

3.Documentación adicional sobre middleware Notas :Apreciaría alguna edición con respecto a mi estilo y sangría del código, ya que parece que luché para diseñar mi código correctamente aquí, pero fue en vano, las sangrías que usé no tuvieron ningún efecto.