Gerçek hayatta Laravel uygulamarında, genellikle aynı işi farklı şekillerde yapan birden fazla servis sınıfı ile çalışırız. Örneğin, birden fazla ödeme geçidi, dış API sağlayıcıları veya bildirim hizmetleri.
Bu durum, hangi servisi kullanacağımıza karar vermek noktasında, kodumuzu if-else veya switch ifadeleriyle doldurmadan temiz bir şekilde karar vermek için bir zorluk oluşturur.
Bu yazıda, Laravel’de Resolver pattern’inin nasıl kullanılacağını pratik bir örnekle açıklayacağım.
Sorun: Çok Fazla if-else Koşulu
Uygulamamızda desteklenen birden fazla ödeme geçidi olduğunu varsayalım: Stripe ve PayPal.
Yaygın bir yaklaşım şu şekildedir:
if ($paymentType === 'stripe') {
$service = new StripePaymentService();
} elseif ($paymentType === 'paypal') {
$service = new PaypalPaymentService();
} else {
throw new Exception();
}
$service->charge($data);
Bu yaklaşımda ne yanlış?
- İş mantığı sıkı bir şekilde bağlı.
- Yeni bir ödeme geçidi eklemek mevcut kodu değiştirmeyi gerektiriyor.
- Test etmesi ve bakım yapması zor.
- Açık/Kapalı Prensibi’ni ihlal ediyor.
Bu kod çalışıyor, ancak ölçeklenebilirliği düşük.
Resolver Nedir?
Resolver, çalışma zamanı verilerine dayanarak hangi servis implementasyonunun kullanılacağını belirleyen bir sınıftır.
Basitçe şu şekilde tanımlanabilir:
Bir resolver, sizin için doğru servis sınıfını döner; böylece iş mantığınız temiz kalır.
Gerçek Dönüşüm: Ödeme Servisi Resolver’ı
Yukarıdaki örneği bir Resolver pattern’i kullanarak tekrar düzenleyelim.
Adım 1: Ortak Bir Arayüz Oluşturma
Tüm ödeme servisleri aynı sözleşmeyi takip etmelidir.
interface PaymentServiceInterface
{
public function charge(array $data): bool;
}
Adım 2: Servis Implementasyonları Oluşturma
Stripe Servisi
class StripePaymentService implements PaymentServiceInterface
{
public function charge(array $data): bool
{
// Stripe ödeme mantığı
return true;
}
}
PayPal Servisi
class PaypalPaymentService implements PaymentServiceInterface
{
public function charge(array $data): bool
{
// PayPal ödeme mantığı
return true;
}
}
Her servis kendi mantığını işler, ancak hepsi aynı arayüzü takip eder.
Adım 3: Resolver Sınıfı Oluşturma
class PaymentServiceResolver
{
public function __construct(
public readonly StripePaymentService $stripePaymentService,
public readonly PaypalPaymentService $paypalPaymentService
) {}
public function resolve(string $type): PaymentServiceInterface
{
return match ($type) {
=> $this->stripePaymentService,
=> $this->paypalPaymentService,
default => throw new InvalidArgumentException(),
};
}
}
Neden constructor injection kullanılır?
- Bağımlılıkları açık ve daha anlaşılır hale getirir.
- Ünite test edilebilirliği artırır (servisleri kolayca mocklayabilirsiniz).
- Resolver’ı temiz ve odaklı tutar.
- Laravel’ın bağımlılık enjeksiyon konteynerinin tüm avantajlarını kullanır.
💡 Not: Servisleri resolver içinde app() ile çözümleyebilirsiniz, ancak constructor injection genellikle daha temiz bir mimari ve daha iyi test edilebilirlik sağlar.
Adım 4: Resolver’ı İş Mantığınızda Kullanın
class PaymentController extends Controller
{
public function store(
Request $request,
PaymentServiceResolver $resolver
) {
$paymentType = $request->get();
$service = $resolver->resolve($paymentType);
$service->charge($request->all());
return response()->json([
]);
}
}
✨ Temiz, okunabilir ve genişletilebilir.
Yeni Bir Servis Eklemek Kolay
Sonradan Razorpay eklemek ister misiniz?
=> $this->razorpayPaymentService,
Kontrolörlerde veya iş mantığında herhangi bir değişiklik yapmanıza gerek kalmaz.
Resolver Kullanmanın Faydaları
✅ Daha temiz ve okunabilir kod
✅ Yeni hizmetleri kolayca ekleme
✅ SOLID prensiplerine uyma
✅ Merkezi hizmet seçimi mantığı
✅ Birim testlerini kolaylaştırma
Bonus: Resolver’ı Daha Esnek Hale Getirme
Değerleri hardcode etmek yerine, eşleştirmeyi bir yapılandırma dosyasına taşıyabilirsiniz:
// config/payment.php
return [
=> StripePaymentService::class,
=> PaypalPaymentService::class,
];
Resolver
class PaymentServiceResolver
{
public function resolve(string $type): PaymentServiceInterface
{
$service = config($type);
if (! $service) {
throw new InvalidArgumentException();
}
return app($service);
}
}
Bu, sisteminizi daha da yapılandırılabilir hale getirir.
Son Düşünceler
Resolvers, Laravel’de birden fazla servis implementasyonunu yönetmek için basit ancak güçlü bir pattern’dır.
Birden fazla API, ödeme geçidi veya sağlayıcı ile çalışıyorsanız, Resolvers kod kalitenizi önemli ölçüde artırabilir.
Kaynak: Laravel


