sql >> Databasteknik >  >> RDS >> Mysql

Hur ansluter jag till olika databaser under körning?

Jag snubblade över den här frågan och det hade mitt svar.

Jag skapade en klass som heter 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;
        }
}

Så när jag är i en kontroller som manipulerar tabeller i en underdatabas, går jag helt enkelt till så här:

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

Extra bonus :

Användningen av det statiska attributet $instances i min DatabaseConnection handlar om att hämta min senaste databasanslutning för enkel användning.

Till exempel, om jag någonsin skulle vilja hämta det, skulle det vara insvept i en funktion som

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

Anteckningar :

Om du stöter på fel som Unknown class 'Container' eller Capsule eller något sådant, se till att du kontrollerar frågelänken jag har tillhandahållit och använd use uttalanden korrekt.

Angående kommande svar :

Det verkar för mig som om denna databasanslutning lever inom parentesen för kontrollenhetens åtgärd, så när jag fortsätter till en annan åtgärd som inte anger någon anslutning, återgår den automatiskt till den centrala databasen.

Vilket har fått mig att tänka att det måste finnas ett sätt att ställa in databasanslutningen till underdatabasen på ett "globalt" sätt för hela funktionen, som en mellanprogramvara eller något.

Jag skulle älska att se ett svar, implementera en sådan sak.

Uppdatera :

Jag kom på ett snyggare sätt att göra det på.

Jag antar att du är på samma grund som jag och vill ändra databaser villkorligt i enlighet med varje kontrollant... säg, var och en av dina kontroller kräver en annan databas, bara för argumentets skull.

Det vi kommer att använda för att lösa detta är `Middlewares.

Först, för att förklara vad vi ska göra...

Vi kommer att leta efter namnet på kontrollern (och till och med åtgärden) och sedan ställa in den korrekta databas vi vill ställa in.

  1. Gå till din kommandorad, skriv in:

    php artisan make:middleware SetDatabaseConnectionMiddleware

För att skapa en mellanvara med färdig pannplåt.

Eller, om du gillar det den svåra vägen, gå till din app_name/app/Http/Middleware och skapa en manuellt.

  1. Gå till din hjälpmetodfil (om du redan har en, om inte, gör en!)

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

Detta kommer att returnera till dig en array med både åtgärdsnamnet och kontrollenhetens namn, om du vill returnera restriktivt bara kontrollenhetens namn, ta bort 'action' => $action från koden.

  1. Inuti ditt mellanprogram kommer det att se ut så här:

    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.Nu, när du har skapat din mellanprogram på rätt sätt, låt oss berätta för din app var den kan hittas och under vilket namn.

  1. Gå till ditt app_name/app/Http/Kernel.php
  2. I din $routeMiddleware variabel, lägg till den här raden

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

På så sätt vet vi hur man kallar det.

  1. Slutligen, ställ in det.

    1. Gå till din Controller.php (den abstrakta klassen som alla dina kontroller ärver från)

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

Och det här borde göra det åt dig.

Om du har ytterligare frågor får du gärna kommentera.

// Resurser :

1.Kontroller och åtgärdsnamn

2.dokumentation för mellanprogram

3.Ytterligare Middleware-dokumentation Anteckningar :Jag skulle uppskatta en utgåva angående min styling och kodindrag, eftersom det verkar som om jag kämpade för att styla min kod ordentligt här men förgäves, indragen jag använde hade ingen effekt.




  1. Hur tvingar man fram återanvändning av anslutningar i jdbc pool?

  2. Kan vi ha flera MED AS i singel sql - Oracle SQL

  3. Mysql INSERT IGNORE om vissa radvärden i två kolumner redan finns

  4. Returnera det aktuella inloggningsnamnet i SQL Server (T-SQL)