Mysql
 sql >> Database >  >> RDS >> Mysql

Come mi collego a database diversi in fase di esecuzione?

Mi sono imbattuto in questa domanda e aveva la mia risposta.

Ho creato una classe chiamata 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;
        }
}

Quindi, ogni volta che mi trovo in un controller che manipola le tabelle di un sottodatabase, vado semplicemente in questo modo:

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

Bonus extra :

L'uso dell'attributo statico $instances nel mio DatabaseConnection si riduce al recupero della mia ultima connessione al database per un facile utilizzo.

Ad esempio, se mai volessi recuperarlo, verrebbe racchiuso in una funzione come

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

Note :

Se riscontri errori come Unknown class 'Container' o Capsule o qualcosa del genere, assicurati di controllare il link alla domanda che ho fornito e usa use affermazioni correttamente.

Riguardo alle prossime risposte :

Mi sembra che questa connessione al database risieda all'interno delle parentesi dell'azione del controller, quindi quando procedo a un'altra azione che non specifica alcuna connessione, ritorna automaticamente al database centrale.

Il che mi ha fatto pensare che ci debba essere un modo per impostare la connessione del database al sottodatabase in modo "globale" per l'intera funzione, come un middleware o qualcosa del genere.

Mi piacerebbe vedere una risposta, implementando una cosa del genere.

Aggiorna :

Ho trovato un modo più ordinato per farlo.

Presumo che tu sia sul mio stesso terreno, volendo modificare i database in modo condizionale in base a ciascun controller... ad esempio, ciascuno dei tuoi controller richiede un database diverso, solo per il bene dell'argomento.

Quello che useremo per risolvere questo problema è `Middlewares.

Innanzitutto, per spiegare cosa stiamo per fare..

Verificheremo il nome del controller (e anche l'azione) e quindi imposteremo il database corretto che desideriamo impostare.

  1. Vai alla tua riga di comando, digita:

    php artisan make:middleware SetDatabaseConnectionMiddleware

Per creare un middleware con boilerplate pronto.

Oppure, se ti piace nel modo più difficile, vai su nome_app/app/Http/Middleware e creane uno manualmente.

  1. Vai al tuo file dei metodi di supporto (se ne hai già uno, in caso contrario, creane uno!)

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

Questo ti restituirà un array con sia il nome dell'azione che il nome del controller, se vuoi restituire in modo restrittivo solo il nome del controller, sentiti libero di rimuovere 'action' => $action dal codice.

  1. All'interno del tuo middleware, apparirà in questo modo:

    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.Ora, che hai creato correttamente il tuo middleware, lasciaci dire alla tua app dove trovarlo e con quale nome.

  1. Vai a nome_app/app/Http/Kernel.php
  2. Nel tuo $routeMiddleware variabile, aggiungi questa riga

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

In questo modo sappiamo come chiamarlo.

  1. Infine, la configurazione.

    1. Vai al tuo Controller.php (la classe Abstract da cui ereditano tutti i tuoi controller)

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

E questo dovrebbe farlo per te.

Se hai altre domande, non esitare a commentare.

// Risorse :

1.Nome controller e azione

2.Documentazione sul middleware

3.Ulteriore documentazione sul middleware Note :Apprezzerei qualche edizione riguardante il mio stile e il rientro del codice, dato che sembra che ho faticato a definire correttamente il mio codice qui, ma invano, i rientri che ho usato non hanno avuto alcun effetto.