Facade & helper
Facade adalah jalan pintas bertipe menuju objek di dalam container. Ia sangat nyaman, punya kemampuan tes yang bagus, dan menyembunyikan dependensi — ketiganya benar sekaligus.
Intisari
Cache::get()sebenarnya memanggil method biasa pada objek yang di-resolve dari container.- Karena lewat container, facade bisa diganti saat tes:
Mail::fake(),Queue::fake(),Storage::fake(). - Kelemahannya: dependensi jadi tidak terlihat di signature — kelas jadi lebih sulit dibaca dan dipakai ulang.
- Aturan praktis: facade di controller dan route, injeksi konstruktor di kelas domain.
- Real-time facade (
Facades\App\...) memberi kemampuanfake()tanpa menulis facade sendiri.
Yang sebenarnya terjadi
Cache::put('kunci', 'nilai', 60);
// Setara dengan:
app('cache')->put('kunci', 'nilai', 60);
Kelas Cache hanya menyimpan satu string — nama layanan di container. Panggilan statis apa pun
dilempar ke objek nyata lewat __callStatic. Karena itu seluruh lapisan facade tetap bisa
diganti saat tes: yang kamu ganti adalah isi container, bukan kelas facade-nya.
Kekuatannya: fake()
public function test_pesanan_mengirim_email_dan_job(): void
{
Mail::fake();
Queue::fake();
Storage::fake('s3');
$this->post('/pesanan', [...]);
Mail::assertSent(KonfirmasiPesanan::class, fn ($m) => $m->hasTo('[email protected]'));
Queue::assertPushed(KirimInvoice::class);
Storage::disk('s3')->assertExists('invoice/1.pdf');
}
Tidak ada email terkirim, tidak ada job diproses, tidak ada berkas naik ke S3 — tapi kamu punya kepastian bahwa kodenya melakukan ketiganya. Ini keuntungan facade yang paling nyata, dan alasan kenapa ia tidak pantas dihindari secara membabi buta.
Kelemahannya: dependensi tersembunyi
// Dengan facade — apa saja yang dipakai kelas ini? Harus dibaca seluruh isinya.
class HitungOngkir
{
public function untuk(Pesanan $p): int
{
$tarif = Cache::remember("tarif:{$p->kota}", 3600,
fn () => Http::get(config('services.ongkir.url'))->json());
Log::info('ongkir dihitung', ['pesanan' => $p->id]);
return $tarif['harga'];
}
}
// Dengan injeksi — dependensinya tertulis di satu tempat, dan bisa diganti tanpa facade
class HitungOngkir
{
public function __construct(
private readonly Repository $cache,
private readonly PenyediaOngkir $penyedia,
) {}
}
| Tempat | Pilihan yang sehat | Alasan |
|---|---|---|
| Route closure, controller tipis | Facade / helper | Singkat, dan sudah pasti berjalan di dalam Laravel |
| Form request, middleware | Facade | Sama |
| Kelas domain, action, service | Injeksi konstruktor | Dependensinya jelas dan bisa diuji tanpa framework |
| Paket yang bisa dipakai ulang | Injeksi konstruktor | Tidak mengikat diri ke facade aplikasi |
| Job dan listener | Injeksi di handle() | Container tetap mengisinya otomatis |
Facade, helper, dan objek — tiga bentuk hal yang sama
Cache::get('k'); app('cache')->get('k'); cache('k');
Session::get('k'); session('k');
Config::get('app.name'); config('app.name');
Response::json($d); response()->json($d);
Redirect::route('beranda'); redirect()->route('beranda');
Auth::user(); auth()->user(); $request->user();
Untuk pengguna aktif, $request->user() adalah bentuk terbaik. Ia menyatakan bahwa
identitas datang dari permintaan yang sedang diproses. auth()->user() membaca keadaan global —
dan di worker mode, keadaan global adalah tempat kebocoran antar-pengguna bermula. Di dalam job antrean,
keduanya bahkan tidak berlaku: job harus membawa user_id-nya sendiri.
Real-time facade
use Facades\App\Services\GerbangPembayaran; // awalan "Facades\"
GerbangPembayaran::tagih($pesanan); // kelasmu sendiri, dipanggil seperti facade
// dan bisa di-mock seperti facade bawaan
GerbangPembayaran::shouldReceive('tagih')->once()->andReturnTrue();
Berguna saat kamu perlu kemampuan mock tanpa mengubah signature kelas. Tetap saja, untuk kelas domain inti, injeksi konstruktor lebih jujur — orang berikutnya yang membaca kelasmu bisa melihat ketergantungannya tanpa membaca isinya.
Latihan: tulis satu controller yang memakai Mail::send(), lalu tulis tesnya dengan
Mail::fake() dan Mail::assertSent(). Setelah hijau, refactor logikanya ke sebuah kelas
action yang menerima Mailer lewat konstruktor — dan rasakan bedanya saat menulis tes yang kedua.
Rangkuman ini sengaja dipangkas ke bagian yang dipakai di roadmap. Buka sumber aslinya saat kamu butuh detail lengkap atau referensi parameter.