Multi-Tenant
Cara data tiap sekolah dipisahkan, koneksi, dan jebakan yang sering terjadi
Konsep
Setiap sekolah adalah satu tenant dengan database sendiri. Data umum disimpan di database central.
| Koneksi | Dipakai untuk |
|---|---|
mysql | Database central |
school | Database tenant yang sedang aktif |
Bagaimana tenant dipilih
Pemilihan tenant dilakukan middleware SwitchDatabase (berbasis session) dan TenantSwitcher.
Langkah rincinya:
User login. Sistem mengetahui sekolah milik user tersebut.
Middleware menyimpan sekolah aktif di session.
Pada setiap request, middleware mengarahkan koneksi school ke database sekolah tersebut.
TenantSwitcher memakai Redis untuk cache. Jika Redis tidak tersedia, sistem fallback ke resolusi berbasis token.
Di Windows lokal, ekstensi PHP Redis biasanya belum terpasang. Akibatnya log menampilkan Class "Redis" not found dari TenantSwitcher. Ini hanya peringatan, sistem tetap jalan lewat fallback token.
Web dan API memakai model user yang berbeda
| Aplikasi | Model user | Catatan |
|---|---|---|
| Web Sekolah | TenantUser | Koneksi school |
| API-Sekolah | App\Models\User\User | Guard terpisah |
Karena itu nilai model_type di model_has_roles bisa berbeda. Untuk siswa dan wali, API memakai guard school dengan provider TenantUser.
Jebakan yang sering terjadi
Daftar bug berulang di arsitektur multi-tenant, urut dari yang paling sering:
model_typetidak cocok antar koneksimysqldanschool. Role tidak terbaca atau login gagal.- Scope
->role()memakai koneksi yang salah. Contoh: dropdown guru di jadwal kosong karena->role('Teacher')mencari ke central, padahalmodel_has_rolesada di tenant. property_exists()pada model Eloquent selalu gagal untuk atribut magic. Pakaiisset()atau$model->getAttribute().- Middleware tenant menimpa koneksi
mysql. Halaman super admin yang butuh data central harus memakai koneksicentralsecara eksplisit, bukanmysql. Contoh nyata: halaman/languagekosong. - Hierarki class user (
TenantUser,App\Models\User,App\Models\User\User) membingungkan. Cek dulu class mana yang dipakai di konteks tersebut.
Kebocoran data antar tenant adalah bug paling berbahaya. Uji setiap fitur baru dengan minimal dua sekolah.
Aturan saat menulis kode
- Selalu tentukan koneksi pada model:
protected $connection = 'school'; - Jangan campur query central dan tenant dalam satu transaksi.
- Jangan buat foreign key lintas database.
- Job queue harus membawa informasi tenant supaya berjalan di database yang benar.
- Untuk data lintas tenant (misalnya super admin melihat semua contact inquiry), query ke setiap database sekolah satu per satu atau gabungkan dengan union, jangan mengandalkan koneksi aktif.
Membuat sekolah baru (provisioning)
Menjalankan migration
php artisan migrateSesuaikan path migration tenant dengan struktur project yang sebenarnya.