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

Hvordan opretter jeg forbindelse til forskellige databaser under kørsel?

Jeg faldt over dette spørgsmål og det havde mit svar.

Jeg lavede en klasse kaldet 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 jeg er i en controller, der manipulerer tabeller i en underdatabase, går jeg simpelthen på denne måde:

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

Ekstra bonus :

Brugen af ​​den statiske attribut $instances i min DatabaseConnection koges ned til at hente min seneste databaseforbindelse for nem brug.

For eksempel, hvis jeg nogensinde ville hente det, ville det blive pakket ind i en funktion som

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

Noter :

Hvis du støder på fejl såsom Unknown class 'Container' eller Capsule eller noget af den slags, sørg for at tjekke spørgsmålslinket, jeg har givet, og brug use udsagn korrekt.

Vedrørende kommende svar :

Det forekommer mig, at denne databaseforbindelse lever inden for parenteserne af controllerens handling, så når jeg fortsætter til en anden handling, der ikke angiver nogen forbindelse, vender den automatisk tilbage til den centrale database.

Hvilket har fået mig til at tænke, at der må være en måde at sætte databaseforbindelsen til underdatabasen på en 'global' måde til hele funktionen, såsom en middleware eller noget.

Jeg ville elske at se et svar, der implementerer sådan noget.

Opdater :

Jeg fandt på en pænere måde at gøre det på.

Jeg går ud fra, at du er på samme grund som mig, og ønsker at ændre databaser betinget i overensstemmelse med hver controller... siger, hver af dine controllere kræver en anden database, bare for argumentets skyld.

Det, vi skal bruge til at løse dette, er `Middlewares.

Først for at forklare, hvad vi er ved at gøre..

Vi vil tjekke efter navnet på controlleren (og endda handling) og derefter indstille den korrekte database, vi ønsker at indstille.

  1. Gå til din kommandolinje, skriv:

    php artisan make:middleware SetDatabaseConnectionMiddleware

At skabe en middleware med klar kedelplade.

Eller, hvis du kan lide det på den hårde måde, skal du gå til din app_name/app/Http/Middleware og oprette en manuelt.

  1. Gå til din hjælpemetodefil (hvis du allerede har en, hvis ikke, lav en fyr!)

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

Dette vil returnere til dig et array med både handlingsnavnet og controllernavnet, hvis du ønsker at returnere begrænset kun controllerens navn, er du velkommen til at fjerne 'action' => $action fra koden.

  1. Inde i din middleware vil det se sådan ud:

    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, hvor du har oprettet din middleware korrekt, så lad os fortælle din app, hvor den kan finde den og under hvilket navn.

  1. Gå til dit app_name/app/Http/Kernel.php
  2. I din $routeMiddleware variabel, tilføj denne linje

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

På denne måde ved vi, hvordan man kalder det.

  1. Til sidst skal du sætte det op.

    1. Gå til din Controller.php (den abstrakte klasse, som alle din controllers arver fra)

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

Og dette burde gøre det for dig.

Hvis du har yderligere spørgsmål, er du velkommen til at kommentere.

// Ressourcer :

1.Controller og handlingsnavn

2.Middleware-dokumentation

3.Yderligere Middleware-dokumentation Noter :Jeg ville sætte pris på en udgave angående min styling og kodeindrykning, da det ser ud til, at jeg kæmpede for at style min kode ordentligt herinde, men forgæves, de indrykninger, jeg brugte, havde ingen effekt.




  1. Er der en måde at give brugervenlig fejlmeddelelse om overtrædelse af begrænsninger

  2. SQL Server sp_msforeachtable brug til kun at vælge de tabeller, der opfylder en eller anden betingelse

  3. Forskellen mellem sys.views, sys.system_views og sys.all_views i SQL Server

  4. MySQL brugerdefineret rækkefølge