sql >> Database >  >> RDS >> Mysql

Hoe maak ik tijdens runtime verbinding met verschillende databases?

Ik stuitte op deze vraag en het had mijn antwoord.

Ik heb een klasse gemaakt met de naam 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;
        }
}

Dus wanneer ik in een controller ben die tabellen van een subdatabase manipuleert, ga ik gewoon deze kant op:

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

Extra bonus :

Het gebruik van het statische attribuut $instances in mijn DatabaseConnection komt neer op het ophalen van mijn nieuwste databaseverbinding voor gebruiksgemak.

Als ik het bijvoorbeeld ooit zou willen ophalen, zou het verpakt zijn in een functie zoals

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

Opmerkingen :

Als u fouten tegenkomt zoals Unknown class 'Container' of Capsule of iets dergelijks, zorg ervoor dat je de vraaglink die ik heb verstrekt, controleert en gebruik use verklaringen correct.

Over komende antwoorden :

Het lijkt mij dat deze databaseverbinding zich tussen de haakjes van de actie van de controller bevindt, dus wanneer ik doorga naar een andere actie die geen verbinding specificeert, keert deze automatisch terug naar de centrale database.

Dat heeft me aan het denken gezet dat er een manier moet zijn om de databaseverbinding met de subdatabase op een 'algemene' manier in te stellen voor de hele functie, zoals een middleware of zoiets.

Ik zou graag een antwoord zien om zoiets te implementeren.

Bijwerken :

Ik heb een nettere manier bedacht om het te doen.

Ik neem aan dat u op dezelfde grond zit als ik, dat u databases voorwaardelijk wilt wijzigen in overeenstemming met elke controller... zeg, elk van uw controllers heeft een andere database nodig, alleen omwille van het argument.

Wat we gaan gebruiken om dit op te lossen is `Middlewares.

Allereerst om uit te leggen wat we gaan doen..

We gaan de naam van de controller (en zelfs actie) controleren en vervolgens de juiste database instellen die we willen instellen.

  1. Ga naar je opdrachtregel , typ in:

    php artisan make:middleware SetDatabaseConnectionMiddleware

Een middleware maken met kant-en-klare boilerplate.

Of, als je het op de moeilijke manier leuk vindt, ga naar je app_name/app/Http/Middleware en maak er handmatig een.

  1. Ga naar je bestand met hulpmethoden (als je er al een hebt, zo niet, maak er dan een!)

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

Hiermee krijgt u een array terug met zowel de actienaam als de controllernaam. Als u beperkt alleen de naam van de controller wilt retourneren, verwijder dan gerust 'action' => $action van de code.

  1. De binnenkant van uw middleware ziet er zo uit:

    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 u uw middleware correct heeft gemaakt, laten we uw app vertellen waar deze te vinden is en onder welke naam.

  1. Ga naar je app_name/app/Http/Kernel.php
  2. In uw $routeMiddleware variabele, voeg deze regel toe

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

Zo weten we hoe we het moeten noemen.

  1. Eindelijk, het instellen.

    1. Ga naar uw Controller.php (de klasse Abstract waarvan al uw controllers erven)

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

En dit zou het voor je moeten doen.

Als je nog vragen hebt, kun je reageren.

// Bronnen :

1.Controller en actienaam

2.Middleware-documentatie

3.Verdere middleware-documentatie Opmerkingen :Ik zou graag een editie willen over mijn stijl en code-inspringing, aangezien het lijkt alsof ik moeite had om mijn code hier goed te stylen, maar tevergeefs, de inspringingen die ik gebruikte hadden geen effect.




  1. Mysql inline laden - specifieke kolommen

  2. Fout in tijdstempelkolom mysql

  3. Hoe u Foreign Key Check in MySQL uitschakelt?

  4. Stopwoorden en Stoplist gebruiken om SQL Server Full-Text Search (FTS) te verbeteren