Mysql
 sql >> Datenbank >  >> RDS >> Mysql

Wie verbinde ich mich zur Laufzeit mit verschiedenen Datenbanken?

Ich bin über diese Frage gestolpert und es hatte meine Antwort.

Ich habe eine Klasse namens DatabaseConnection erstellt :

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;
        }
}

Wenn ich mich also in einem Controller befinde, der Tabellen einer Unterdatenbank manipuliert, gehe ich einfach diesen Weg:

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

Extrabonus :

Die Verwendung des statischen Attributs $instances in meiner DatabaseConnection läuft darauf hinaus, meine neueste Datenbankverbindung für eine einfachere Verwendung abzurufen.

Wenn ich es zum Beispiel jemals abrufen wollte, würde es in eine Funktion wie

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

Notizen :

Wenn Fehler wie Unknown class 'Container' auftreten oder Capsule oder irgendetwas in dieser Art, vergewissern Sie sich, dass Sie den Fragelink überprüfen, den ich bereitgestellt habe, und verwenden Sie use Anweisungen richtig.

In Bezug auf bevorstehende Antworten :

Es scheint mir, dass diese Datenbankverbindung innerhalb der Klammern der Aktion des Controllers lebt. Wenn ich also zu einer anderen Aktion übergehe, die keine Verbindung angibt, kehrt sie automatisch zur zentralen Datenbank zurück.

Was mich zum Nachdenken gebracht hat, dass es eine Möglichkeit geben muss, die Datenbankverbindung zur Unterdatenbank auf 'globale' Weise für die gesamte Funktion festzulegen, z. B. eine Middleware oder so etwas.

Ich würde gerne eine Antwort sehen, die so etwas implementiert.

Aktualisieren :

Ich habe mir einen einfacheren Weg ausgedacht.

Ich nehme an, Sie sind auf der gleichen Grundlage wie ich, wenn Sie Datenbanken bedingt in Übereinstimmung mit jedem Controller ändern möchten ... sagen Sie, jeder Ihrer Controller benötigt eine andere Datenbank, nur um des Arguments willen.

Was wir verwenden werden, um dieses Problem zu lösen, sind `Middlewares.

Zuerst, um zu erklären, was wir tun werden..

Wir werden nach dem Namen des Controllers (und sogar der Aktion) suchen und dann die richtige Datenbank festlegen, die wir festlegen möchten.

  1. Gehen Sie zu Ihrer Befehlszeile, geben Sie ein:

    php artisan make:middleware SetDatabaseConnectionMiddleware

So erstellen Sie eine Middleware mit fertiger Boilerplate.

Oder, wenn Sie es auf die harte Tour mögen, gehen Sie zu Ihrer app_name/app/Http/Middleware und erstellen Sie manuell eine.

  1. Gehen Sie zu Ihrer Hilfsmethodendatei (wenn Sie bereits eine haben, wenn nicht, erstellen Sie eine!)

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

Dies gibt Ihnen ein Array mit sowohl dem Aktionsnamen als auch dem Controller-Namen zurück. Wenn Sie nur den Namen des Controllers restriktiv zurückgeben möchten, können Sie 'action' => $action entfernen aus dem Code.

  1. Innerhalb Ihrer Middleware sieht es so aus:

    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. Nachdem Sie nun Ihre Middleware richtig erstellt haben, lassen Sie uns Ihrer App mitteilen, wo und unter welchem ​​Namen sie zu finden ist.

  1. Gehe zu deinem app_name/app/Http/Kernel.php
  2. In Ihrer $routeMiddleware Variable, fügen Sie diese Zeile hinzu

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

Auf diese Weise wissen wir, wie man es nennt.

  1. Endlich einrichten.

    1. Gehe zu deiner Controller.php (die abstrakte Klasse, von der alle Ihre Controller erben)

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

Und das sollte es für Sie tun.

Wenn Sie weitere Fragen haben, können Sie gerne einen Kommentar hinterlassen.

// Ressourcen :

1.Name des Controllers und der Aktion

2.Middleware-Dokumentation

3.Weitere Middleware-Dokumentation Notizen :Ich würde mich über einige Änderungen in Bezug auf mein Styling und Code-Einrückungen freuen, da ich anscheinend damit zu kämpfen hatte, meinen Code hier richtig zu stylen, aber vergebens, die von mir verwendeten Einrückungen hatten keine Wirkung.