2026'da Laravel Events ve Listeners: Olay Odaklı Mimari ve Mülakat Soruları

Laravel 12'de olay ve dinleyici sisteminin kapsamlı rehberi. Observer pattern uygulaması, kuyruk tabanlı listener'lar, veritabanı transaction'ları ve teknik mülakat soruları.

Laravel Events ve Listeners - olay odaklı mimari

Laravel'de events ve listeners sistemi observer pattern uygulayarak, uygulamanın farklı bölümlerinin doğrudan bağımlılık olmaksızın aksiyonlara tepki vermesini sağlar. Bir kullanıcı sipariş verdiğinde OrderShipped olayı tetiklenir ve ayrı dinleyiciler bildirimleri, analizleri ve envanter güncellemelerini bağımsız olarak işler.

Laravel 12 Olay Keşfi

Laravel 12, app/Listeners klasöründeki dinleyicileri otomatik olarak keşfeder. Bir event sınıfını type hint olarak belirten handle veya __invoke metoduna sahip herhangi bir sınıf, yapılandırma dosyası gerekmeden otomatik olarak kaydedilir.

Laravel 12'de Otomatik Olay Keşfi Nasıl Çalışır

Laravel 11'den itibaren EventServiceProvider kaldırıldı. Framework, Listeners dizinini tarar ve her dinleyicinin hangi olaylara yanıt vereceğini handle metodu imzasındaki type hint'e göre belirlemek için reflection kullanır.

app/Listeners/SendOrderConfirmation.phpphp
<?php

namespace App\Listeners;

use App\Events\OrderShipped;

class SendOrderConfirmation
{
    public function handle(OrderShipped $event): void
    {
        // $event->order->user'a onay e-postası gönder
    }
}

Yukarıdaki dinleyici OrderShipped olayları için otomatik olarak kaydedilir. Service provider'da manuel bağlama gerekmez. Bu yaklaşım boilerplate'i azaltır ve olay-dinleyici ilişkilerini uygulayan koda yakın tutar.

Kayıtlı dinleyicileri doğrulamak için php artisan event:list komutunu çalıştırın. Production ortamında, her istekte dizin taramasını atlamak için php artisan event:cache komutuyla olay manifestini önbelleğe alın.

Artisan ile Event ve Listener Oluşturma

Laravel, event ve listener iskeletini oluşturmak için Artisan komutları sağlar:

bash
# Event sınıfı oluştur
php artisan make:event OrderShipped

# Bir event'e bağlı listener oluştur
php artisan make:listener SendShipmentNotification --event=OrderShipped

Oluşturulan event sınıfı üç trait kullanır: statik dispatch() metodu için Dispatchable, broadcasting için InteractsWithSockets ve listener'lar kuyruklandığında Eloquent modellerini serialize etmek için SerializesModels.

app/Events/OrderShipped.phpphp
<?php

namespace App\Events;

use App\Models\Order;
use Illuminate\Foundation\Events\Dispatchable;
use Illuminate\Broadcasting\InteractsWithSockets;
use Illuminate\Queue\SerializesModels;

class OrderShipped
{
    use Dispatchable, InteractsWithSockets, SerializesModels;

    public function __construct(
        public Order $order,
    ) {}
}

Event sınıfı bir veri konteyneridir. Order modelini tutar, başka bir şey tutmaz. İş mantığı event'lere değil, listener'lara aittir.

Controller ve Servislerden Event Gönderme

Event'ler, event sınıfı üzerindeki statik dispatch() metodu kullanılarak gönderilir:

app/Http/Controllers/OrderController.phpphp
<?php

namespace App\Http\Controllers;

use App\Events\OrderShipped;
use App\Models\Order;
use Illuminate\Http\Request;

class OrderController extends Controller
{
    public function ship(Request $request, Order $order)
    {
        // Kargo işleme mantığı...
        
        OrderShipped::dispatch($order);
        
        return redirect()->route('orders.index');
    }
}

Koşullu gönderim için dispatchIf() veya dispatchUnless() kullanılır:

php
// Sadece sipariş takip numarasına sahipse gönder
OrderShipped::dispatchIf($order->tracking_number !== null, $order);

Laravel mülakatlarında başarılı olmaya hazır mısın?

İnteraktif simülatörler, flashcards ve teknik testlerle pratik yap.

Yavaş İşlemler İçin Kuyruklanmış Listener'lar

E-posta gönderen, harici API'ları çağıran veya ağır hesaplamalar yapan listener'lar asenkron olarak çalışmalıdır. ShouldQueue implementasyonu listener'ı kuyruğa iter:

app/Listeners/SendShipmentNotification.phpphp
<?php

namespace App\Listeners;

use App\Events\OrderShipped;
use Illuminate\Contracts\Queue\ShouldQueue;

class SendShipmentNotification implements ShouldQueue
{
    public $queue = 'notifications';
    public $delay = 60; // İşlemeden önce 60 saniye bekle

    public function handle(OrderShipped $event): void
    {
        // $event->order->user'a bildirim gönder
    }
}

Kuyruk bağlantısı ve adı $connection ve $queue özellikleriyle veya runtime metodlarıyla özelleştirilir:

php
public function viaConnection(): string
{
    return 'redis';
}

public function viaQueue(): string
{
    return $this->event->order->priority === 'high' 
        ? 'high-priority' 
        : 'default';
}

shouldQueue ile Koşullu Kuyruklama

Bazen bir listener yalnızca event verilerine göre kuyruklanmalıdır:

php
public function shouldQueue(OrderShipped $event): bool
{
    // Sadece 100$'ın üzerindeki siparişler için kuyrukla
    return $event->order->total >= 10000;
}

Veritabanı Transaction'ları ve Event Zamanlaması

Bir transaction içinde gönderilen kuyruklanmış listener'lar, transaction commit edilmeden önce işlenebilir ve bu da eksik veri hatalarına neden olur. İki çözüm mevcuttur:

1. Global yapılandırma config/queue.php içinde:

php
'connections' => [
    'redis' => [
        'after_commit' => true,
    ],
],

2. Listener bazında ShouldQueueAfterCommit ile:

php
use Illuminate\Contracts\Queue\ShouldQueueAfterCommit;

class UpdateInventory implements ShouldQueueAfterCommit
{
    public function handle(OrderShipped $event): void
    {
        // Siparişi sorgulamak güvenli, transaction commit edilmiş
    }
}

Event'lerin kendisi için, event sınıfında ShouldDispatchAfterCommit implement edin:

php
use Illuminate\Contracts\Events\ShouldDispatchAfterCommit;

class OrderShipped implements ShouldDispatchAfterCommit
{
    // Event sadece transaction commit edildikten sonra gönderilir
}

Duplicate Önleme İçin Unique Listener'lar

ShouldBeUnique arayüzü, biri zaten işlenirken duplicate listener'ların kuyruğa eklenmesini önler:

php
use Illuminate\Contracts\Queue\ShouldBeUnique;
use Illuminate\Contracts\Queue\ShouldQueue;

class ProcessLicenseKey implements ShouldQueue, ShouldBeUnique
{
    public $uniqueFor = 3600; // Kilit 1 saat sonra sona erer

    public function uniqueId(LicensePurchased $event): string
    {
        return 'license:' . $event->license->id;
    }

    public function handle(LicensePurchased $event): void
    {
        // Lisans anahtarı oluştur ve ata
    }
}

Aynı lisans ID'si hızlı bir şekilde birden fazla event tetiklerse, yalnızca ilk listener işler. Sonraki denemeler kilidin tutulduğunu bulur ve kuyruğa eklemeyi atlar.

İlişkili Event'ler İçin Event Subscriber'lar

Birden fazla ilişkili event ortak işleme mantığını paylaştığında, event subscriber'lar handler'ları tek bir sınıfta gruplar:

app/Listeners/UserActivitySubscriber.phpphp
<?php

namespace App\Listeners;

use Illuminate\Auth\Events\Login;
use Illuminate\Auth\Events\Logout;
use Illuminate\Events\Dispatcher;

class UserActivitySubscriber
{
    public function handleLogin(Login $event): void
    {
        // Başarılı girişi logla, last_login timestamp'ini güncelle
    }

    public function handleLogout(Logout $event): void
    {
        // Çıkışı logla, session verilerini temizle
    }

    public function subscribe(Dispatcher $events): array
    {
        return [
            Login::class => 'handleLogin',
            Logout::class => 'handleLogout',
        ];
    }
}

Subscriber'lar otomatik keşif kurallarına uyar. Subscriber sınıfındaki handler metodları uygun şekilde type hint edilmiş parametrelere sahipse, Laravel bunları otomatik olarak kaydeder.

Union Types ile Birden Fazla Event'i Dinleme

Tek bir listener, PHP 8 union types kullanarak birden fazla event türüne yanıt verebilir:

php
public function handle(OrderShipped|OrderCancelled $event): void
{
    match (true) {
        $event instanceof OrderShipped => $this->notifyShipped($event),
        $event instanceof OrderCancelled => $this->notifyCancelled($event),
    };
}

Bu pattern, farklı event türleri için benzer mantığı izleyen bildirimler için iyi çalışır.

Event::defer ile Event'leri Erteleme

Laravel 12, bir kod bloğu tamamlanana kadar event gönderimini ertelemek için Event::defer() metodunu tanıttı. Bu, listener'ların tüm ilişkili kayıtlara erişimini sağlar:

php
use Illuminate\Support\Facades\Event;

Event::defer(function () {
    $user = User::create(['name' => 'John']);
    $user->posts()->create(['title' => 'Welcome']);
});
// Hem User hem de Post oluşturma event'leri burada gönderilir

Closure içinde bir exception oluşursa, ertelenen event'ler hiçbir zaman gönderilmez.

Pratik yapmaya başla!

Mülakat simülatörleri ve teknik testlerle bilgini test et.

Laravel Events ve Listeners Mülakat Soruları

Teknik mülakatlar sıklıkla olay odaklı mimari anlayışını test eder. Deneyimli Laravel geliştiricilerini ayırt eden sorular şunlardır:

S: Laravel 12, EventServiceProvider olmadan listener'ları nasıl kaydeder?

Laravel, reflection kullanarak app/Listeners dizinini tarar. Her listener'ın hangi event'e yanıt vereceğini belirlemek için handle() veya __invoke() metodlarındaki type hint'i okur. Production'da php artisan event:cache ile manifesti önbelleğe alın.

S: Bir listener ne zaman ShouldQueue implement etmelidir?

İşlem birkaç milisaniyeden uzun sürdüğünde: e-posta gönderme, harici API çağırma, rapor oluşturma veya dosya işleme. Senkron listener'lar HTTP yanıtını bloke eder.

S: ShouldQueueAfterCommit hangi sorunu çözer?

Kuyruklanmış listener'lar veritabanı transaction'ı commit edilmeden önce işlenebilir. Listener yeni oluşturulan bir kaydı sorgularsa, veri henüz commit edilmediği için başarısız olur. ShouldQueueAfterCommit kuyruk gönderimini transaction tamamlanana kadar erteler.

S: Aynı event için duplicate işlemeyi nasıl önlersiniz?

ShouldBeUnique implement edin. uniqueId() metodunun event verilerine dayalı bir cache anahtarı döndürmesini sağlayın. Listener atomik bir kilit alır ve kilit tutuluyorsa duplicate gönderimler atlanır.

S: Event listener ile event subscriber arasındaki fark nedir?

Listener tek bir event türünü işler. Subscriber, birden fazla ilişkili event için handler'ları tek bir yerde kaydeden bir sınıftır ve kimlik doğrulama event'lerini veya audit logging'i gruplamak için kullanışlıdır.

Laravel Events'in Ölçeklenebilir Uygulamalar İçin Önemi

  • Event'ler bileşenleri ayırarak bildirimler ve analizler gibi özelliklerin bağımsız olarak gelişmesine olanak tanır
  • Kuyruklanmış listener'lar yavaş işlemleri aktararak HTTP yanıtlarını hızlı tutar
  • ShouldQueueAfterCommit kuyruk worker'ları ile veritabanı transaction'ları arasındaki race condition'ları önler
  • Laravel 12'deki otomatik keşif yapılandırma yükünü kaldırarak listener mantığını uygulamaya yakın tutar
  • Event subscriber'lar ilişkili event işlemeyi birleştirir ve kullanıcı aktivite takibi gibi yaygın pattern'ler için dosya dağılımını azaltır
  • SharpSkill üzerindeki /technologies/laravel/interview-questions/events-listeners modülü bu pattern'leri interaktif sorularla kapsar
Günün meydan okuması

Laravel kodundaki hatayı bulabilir misin?

Gerçek bir kod parçası, gizli bir hata, günde bir deneme. Denemek için hesap gerekmez.

Anthony Fillion-Maillet

Yazan:

Anthony Fillion-Maillet

SharpSkill kurucusu

10 yılı aşkın süredir fullstack geliştirici. SharpSkill’i yönetiyor ve burada yayımlanan her şeyden sorumlu.

20 Ağustos 2026 tarihinde güncellendi

Etiketler

#laravel
#events
#listeners
#php
#olay odaklı mimari

Paylaş

İlgili makaleler