sql >> データベース >  >> RDS >> Mysql

実行時に異なるデータベースに接続するにはどうすればよいですか?

    私はこの質問 に出くわしました そしてそれは私の答えでした。

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

    したがって、サブデータベースのテーブルを操作するコントローラーを使用しているときは、次のようにします。

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

    追加ボーナス

    静的属性$instancesの使用 私のDatabaseConnectionで 簡単に使用できるように、最新のデータベース接続を取得することになります。

    たとえば、取得したい場合は、

    などの関数でラップされます。
    function CurrentOrLatestDbConnection()
    {
        if( !empty(DatabaseConnection::$instances) )
        {
            return end(DatabaseConnection::$instances)->getConnection()->getDatabaseName();
        }
    }
    

    メモ

    Unknown class'Container'などのエラーが発生した場合 またはCapsule またはそのようなものについては、私が提供した質問リンクを確認し、 useを使用してください。 正しくステートメントします。

    今後の回答について

    このデータベース接続はコントローラーのアクションの括弧内にあるように思われるため、接続を指定しない別のアクションに進むと、自動的に中央データベースに戻ります。

    そのため、ミドルウェアなどの機能全体に対して「グローバル」な方法でサブデータベースへのデータベース接続を設定する方法が必要だと思いました。

    そのようなことを実行して、答えを見てみたいです。

    更新

    私はそれを行うためのより良い方法を思いついた。

    あなたは私と同じ立場にあり、各コントローラーに応じて条件付きでデータベースを変更したいと思っていると思います...たとえば、議論のために、各コントローラーには異なるデータベースが必要です。

    これを解決するために使用するのは「ミドルウェア」です。

    まず、これから行うことを説明します。

    コントローラの名前(さらにはアクション)を確認してから、設定する適切なデータベースを設定します。

    1. コマンドラインに移動し、次のように入力します:

      php artisan make:middleware SetDatabaseConnectionMiddleware

    ボイラープレートの準備ができたミドルウェアを作成するには。

    または、難しい方法が気に入った場合は、app_name / app / Http / Middlewareにアクセスして、手動で作成してください。

    1. ヘルパーメソッドファイルに移動します(すでに持っている場合は、持っていない場合は、作ってください!)

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

    これにより、アクション名とコントローラー名の両方を含む配列が返されます。コントローラー名のみを制限付きで返したい場合は、'action' => $ actionを削除してください。 コードから。

    1. ミドルウェアの内部では、次のようになります:

        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.これで、ミドルウェアが適切に作成されたので、ミドルウェアの場所と名前をアプリに伝えましょう。

    1. app_name / app / Http/Kernel.phpに移動します
    2. $ routeMiddlewareで 変数、この行を追加

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

    このようにして、それを呼び出す方法を知っています。

    1. 最後に、設定します。

      1. Controller.phpに移動します (すべてのコントローラーが継承する抽象クラス)

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

    そして、これはあなたのためにそれをするはずです。

    ご不明な点がございましたら、お気軽にコメントしてください。

    //リソース:

    1. コントローラーとアクションの名前

    2. ミドルウェアのドキュメント

    3. その他のミドルウェアドキュメント メモここでコードを適切にスタイル設定するのに苦労したようですが、無駄に、使用したインデントには効果がなかったため、スタイリングとコードインデントに関するいくつかのエディションをいただければ幸いです。




    1. mysqliで合計行数を取得する方法

    2. TEXT / BLOBを同じテーブルに格納するかどうか?

    3. PHPエラー:非オブジェクトのメンバー関数rowCount()を呼び出す

    4. 主キーをシリアルに作成するにはどうすればよいですか?