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

複数のデータベースにまたがるLaravelのbelongsToMany関係

    非常に簡単です:

    public function bs()
    {
        $database = $this->getConnection()->getDatabaseName();
        return $this->belongsToMany('B', "$database.a_bs", 'a_id', 'b_id');
    }
    

    接続が環境変数に基づいて構成されているため、データベース名を動的に取得しています。 Laravelは、ピボットテーブルがターゲットリレーションと同じデータベースに存在すると想定しているようです。そのため、代わりに、このメソッドが含まれるモデルである「A」レルムに対応するデータベースを参照するように強制されます。

    SQLiteデータベースについて心配していない場合、つまり単体テストの範囲内であれば、必要なのはそれだけです。しかし、もしそうなら、読み続けてください。

    まず、前の例だけでは不十分です。 $ databaseの値は最終的にファイルパスになるため、SQLステートメントを壊さないものにエイリアスを設定し、現在の接続にアクセスできるようにする必要があります。 "ATTACH DATABASE '$database' AS $name" それを行う方法です:

    public function bs()
    {
        $database = $this->getConnection()->getDatabaseName();
        if (is_file($database)) {
            $connection = app('B')->getConnection()->getName();
            $name = $this->getConnection()->getName();
            \Illuminate\Support\Facades\DB::connection($connection)->statement("ATTACH DATABASE '$database' AS $name");
            $database = $name;
        }
        return $this->belongsToMany('B', "$database.a_bs", 'a_id', 'b_id');
    }
    

    警告:トランザクションはこれを台無しにします: 現在の接続がトランザクションを使用している場合、ATTACHDATABASEステートメントは失敗します。 できます にトランザクションを使用する ただし、そのステートメントを実行します。

    一方、関連 接続がトランザクションを使用する場合、結果のデータは現在のデータからはサイレントに非表示になります。私のクエリはエラーなしで実行されましたが、空のままになっていたので、これは私が認めるよりも長い間私を狂わせました。アタッチされたデータベースに実際に書き込まれたデータのみが、アタッチされたデータベースに実際にアクセスできるようです。

    したがって、接続されたデータベースへの書き込みを強制された後でも、テストをそれ自体の後でクリーンアップする必要がある場合があります。簡単な解決策は、$this->artisan('migrate:rollback', ['--database' => $attachedConnectionName]);を使用することです。 。ただし、同じテーブルを必要とする複数のテストがある場合、毎回再構築する必要があるため、これはあまり効率的ではありません。

    より良いオプションは、テーブルを切り捨てることですが、その構造はそのままにしておきます:

    //Get all tables within the attached database
    collect(DB::connection($database)->select("SELECT name FROM sqlite_master WHERE type = 'table'"))->each(function ($table) use ($name) {
            //Clear all entries for the table
            DB::connection($database)->delete("DELETE FROM '$table->name'");
            //Reset any auto-incremented index value
            DB::connection($database)->delete("DELETE FROM sqlite_sequence WHERE name = '$table->name'");
        });
    }
    

    これにより、その接続からすべてのデータが消去されます 、しかし、あなたが適切だと思う方法でそれに何らかの種類のフィルターを適用できなかった理由はありません。または、SQLite DBが簡単にアクセスできるファイルであるという事実を利用して、添付されたファイルを一時ファイルにコピーし、テストの実行後にソースを上書きするために使用することもできます。結果は、トランザクションと機能的に同じになります。



    1. OracleplsqlでgoogletranslateURLを使用する方法

    2. django.core.exceptions.ImproperlyConfigured:MySQLdbモジュールの読み込みエラー:MySQLdbという名前のモジュールがありません

    3. SQL Serverトランザクションログ—パート2

    4. mysqlを使用して日付がdate1とdate2の間にあるかどうかを確認するにはどうすればよいですか?