Kalau Anda sudah membaca artikel tentang apa itu Contract di Laravel 12, artikel ini melanjutkannya dengan contoh penggunaan nyata: bagaimana membuat implementasi Contract sendiri dan kapan ini berguna dalam proyek.
Menggunakan Contract Bawaan Laravel
Contract bawaan Laravel ada di namespace IlluminateContracts*. Contoh yang paling sering dipakai adalah type-hinting di constructor untuk decoupling:
<?php
namespace AppServices;
use IlluminateContractsCacheRepository as CacheContract;
use IlluminateContractsMailMailer as MailerContract;
class NotificationService
{
public function __construct(
private CacheContract $cache,
private MailerContract $mailer,
) {}
public function sendIfNotSent(string $userId, string $template): void
{
$cacheKey = "notification:{$userId}:{$template}";
if ($this->cache->has($cacheKey)) {
return; // Sudah dikirim
}
$this->mailer->send($template, [], fn ($m) => $m->to($userId));
$this->cache->put($cacheKey, true, now()->addDay());
}
}
Service ini bisa ditest dengan mudah — tinggal inject mock CacheContract dan MailerContract.
Membuat Contract Sendiri
Studi kasus: aplikasi yang butuh fitur kirim notifikasi ke berbagai channel (email, SMS, WhatsApp). Dengan Contract, kita bisa ganti implementasi tanpa mengubah kode yang memakainya.
Buat Contract interface di app/Contracts/NotificationChannel.php:
<?php
namespace AppContracts;
interface NotificationChannel
{
public function send(string $recipient, string $message): bool;
public function isAvailable(): bool;
}
Buat beberapa implementasi:
<?php
namespace AppServicesNotifications;
use AppContractsNotificationChannel;
use IlluminateSupportFacadesMail;
class EmailChannel implements NotificationChannel
{
public function send(string $recipient, string $message): bool
{
try {
Mail::raw($message, fn ($m) => $m->to($recipient));
return true;
} catch (Exception $e) {
return false;
}
}
public function isAvailable(): bool
{
return config('mail.default') !== null;
}
}
<?php
namespace AppServicesNotifications;
use AppContractsNotificationChannel;
class WhatsAppChannel implements NotificationChannel
{
public function __construct(
private WhatsAppApiClient $client
) {}
public function send(string $recipient, string $message): bool
{
return $this->client->sendMessage($recipient, $message);
}
public function isAvailable(): bool
{
return !empty(config('services.whatsapp.token'));
}
}
Bind Contract ke Implementasi di Service Provider
<?php
namespace AppProviders;
use AppContractsNotificationChannel;
use AppServicesNotificationsWhatsAppChannel;
use IlluminateSupportServiceProvider;
class AppServiceProvider extends ServiceProvider
{
public function register(): void
{
// Bind default implementation
$this->app->bind(NotificationChannel::class, WhatsAppChannel::class);
}
}
Sekarang di mana saja Anda type-hint NotificationChannel, Laravel otomatis inject WhatsAppChannel:
<?php
namespace AppHttpControllers;
use AppContractsNotificationChannel;
class AlertController extends Controller
{
public function __construct(
private NotificationChannel $channel
) {}
public function send(Request $request): Response
{
$sent = $this->channel->send(
$request->recipient,
$request->message
);
return response()->json(['success' => $sent]);
}
}
Manfaat: Mudah Ganti Implementasi
Kalau besok ingin switch dari WhatsApp ke SMS, cukup ganti binding di service provider:
$this->app->bind(NotificationChannel::class, SmsChannel::class);
Controller dan semua kode yang pakai NotificationChannel tidak perlu diubah sama sekali.
Contoh: Kontekstual Binding
Kalau perlu inject implementasi berbeda di class berbeda:
$this->app->when(AlertController::class)
->needs(NotificationChannel::class)
->give(WhatsAppChannel::class);
$this->app->when(ReportController::class)
->needs(NotificationChannel::class)
->give(EmailChannel::class);
Baca Juga
- Apa Itu Contract di Laravel 12 dan Bagaimana Cara Kerjanya
- Apa Itu Observer di Laravel 12 dan Kapan Menggunakannya
Mau tim yang bantu bangun arsitektur aplikasi Laravel yang scalable? Lihat layanan pengembangan aplikasi kami.
Leave a Reply