Sangat sederhana:
public function bs()
{
$database = $this->getConnection()->getDatabaseName();
return $this->belongsToMany('B', "$database.a_bs", 'a_id', 'b_id');
}
Saya mendapatkan nama database secara dinamis karena koneksi saya dikonfigurasi berdasarkan variabel lingkungan. Laravel tampaknya menganggap tabel pivot ada di database yang sama dengan relasi target, jadi ini akan memaksanya untuk melihat ke database yang sesuai dengan model tempat metode ini berada, ranah 'A' Anda.
Jika Anda tidak khawatir tentang database SQLite, yaitu dalam lingkup pengujian unit, hanya itu yang Anda butuhkan. Tetapi jika ya, teruslah membaca.
Pertama, contoh sebelumnya tidak cukup dengan sendirinya. Nilai $database akan berakhir menjadi jalur file, jadi Anda perlu membuat alias untuk sesuatu yang tidak akan merusak pernyataan SQL, dan membuatnya dapat diakses oleh koneksi saat ini. "ATTACH DATABASE '$database' AS $name"
adalah bagaimana Anda melakukannya:
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');
}
Peringatan:Transaksi mengacaukan ini: Jika koneksi saat ini menggunakan transaksi, pernyataan ATTACH DATABASE akan gagal. Anda bisa gunakan transaksi di dalamnya setelah mengeksekusi pernyataan itu.
Sedangkan, jika terkait koneksi menggunakan transaksi, data yang dihasilkan akan secara diam-diam tidak terlihat oleh data saat ini. Ini membuat saya gila lebih lama daripada yang ingin saya akui, karena pertanyaan saya berjalan tanpa kesalahan, tetapi terus kosong. Tampaknya hanya data yang benar-benar ditulis ke database terlampir yang benar-benar dapat diakses oleh database yang dilampirkan.
Jadi, setelah dipaksa untuk menulis ke database terlampir, Anda mungkin masih ingin pengujian Anda dibersihkan sendiri. Solusi sederhana hanya menggunakan $this->artisan('migrate:rollback', ['--database' => $attachedConnectionName]);
. Tetapi jika Anda memiliki beberapa pengujian yang memerlukan tabel yang sama, hal ini tidak terlalu efisien, karena memaksa mereka harus membangunnya kembali setiap saat.
Pilihan yang lebih baik adalah dengan memotong tabel, tetapi membiarkan strukturnya tetap rapi:
//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'");
});
}
Ini akan menghapus semua data dari koneksi tersebut , tetapi tidak ada alasan Anda tidak dapat menerapkan filter semacam itu sesuai keinginan Anda. Atau, Anda dapat memanfaatkan fakta bahwa SQLite DB adalah file yang mudah diakses, dan cukup salin file terlampir ke file temp, dan gunakan untuk menimpa sumber setelah pengujian selesai dijalankan. Hasilnya akan identik secara fungsional dengan transaksi.