Sitemap

Laravel Observer Sistemi

3 min readNov 5, 2024

Laravel Observer sistemini detaylıca inceleyelim:

1. Observer Nedir?

  • Model olaylarını (events) dinlemek ve yönetmek için kullanılan sınıflardır
  • Eloquent model olaylarını merkezi bir noktadan yönetmeyi sağlar
  • SOLID prensiplerine uygun kod yazmayı destekler

2. Ne Zaman Kullanılır?

Örnek senaryolar:

- Kullanıcı kaydedildiğinde otomatik profil oluşturma
- Ürün stok değişimlerini loglama
- Sipariş durumu değiştiğinde bildirim gönderme
- Dosya silindiğinde storage'dan fiziksel silme işlemi
- Veri değişikliklerinde cache temizleme

3. Observer Oluşturma ve Kaydetme:

a) Observer Oluşturma:

# Observer oluşturma komutu
php artisan make:observer UserObserver --model=User

b) Observer Yapısı:

class UserObserver
{
public function created(User $user)
{
// Kullanıcı oluşturulduğunda
}

public function updated(User $user)
{
// Kullanıcı güncellendiğinde
}

public function deleted(User $user)
{
// Kullanıcı silindiğinde
}

public function restored(User $user)
{
// Soft delete'den geri getirildiğinde
}

public function forceDeleted(User $user)
{
// Zorla silindiğinde
}
}

c) Observer Kaydetme:

// app/Providers/EventServiceProvider.php
use App\Models\User;
use App\Observers\UserObserver;

public function boot()
{
User::observe(UserObserver::class);
}

4. Observer Metodları ve Kullanımları:

a) Creating/Created:

public function creating(User $user)
{
// Kayıt olmadan önce
$user->uuid = Str::uuid();
}

public function created(User $user)
{
// Kayıt olduktan sonra
Profile::create(['user_id' => $user->id]);
}

b) Updating/Updated:

public function updating(User $user)
{
// Güncelleme olmadan önce
if ($user->isDirty('email')) {
$user->email_verified_at = null;
}
}

public function updated(User $user)
{
// Güncelleme olduktan sonra
if ($user->wasChanged('password')) {
Notification::send($user, new PasswordChanged);
}
}

c) Deleting/Deleted:

public function deleting(User $user)
{
// Silinmeden önce
Storage::delete($user->avatar_path);
}

public function deleted(User $user)
{
// Silindikten sonra
Log::info("User {$user->email} was deleted");
}

5. Pratik Örnekler:

a) Ürün Stok Takibi:

class ProductObserver
{
public function updated(Product $product)
{
if ($product->wasChanged('stock')) {
// Stock değişim logu
StockLog::create([
'product_id' => $product->id,
'old_stock' => $product->getOriginal('stock'),
'new_stock' => $product->stock,
'type' => $product->stock > $product->getOriginal('stock')
? 'increase'
: 'decrease'
]);

// Düşük stok bildirimi
if ($product->stock <= $product->min_stock) {
Notification::send(
User::role('inventory-manager')->get(),
new LowStockAlert($product)
);
}
}
}
}

b) Sipariş Durumu Takibi:

class OrderObserver
{
public function updating(Order $order)
{
if ($order->isDirty('status')) {
$order->status_changes = array_merge(
$order->status_changes ?? [],
[
'from' => $order->getOriginal('status'),
'to' => $order->status,
'at' => now(),
'by' => auth()->id()
]
);
}
}

public function updated(Order $order)
{
if ($order->wasChanged('status')) {
// Müşteriye bildirim
$order->customer->notify(new OrderStatusChanged($order));

// Status'a göre işlemler
match ($order->status) {
'shipped' => $this->handleShipped($order),
'delivered' => $this->handleDelivered($order),
'cancelled' => $this->handleCancelled($order),
default => null
};
}
}
}

6. Advanced Kullanımlar:

a) Conditional Observers:

class UserObserver
{
public function created(User $user)
{
if ($user->shouldCreateProfile()) {
Profile::create(['user_id' => $user->id]);
}
}
}

b) Queue Kullanımı:

class UserObserver
{
public function created(User $user)
{
// Arka planda çalıştırma
ProcessUserRegistration::dispatch($user);
}
}

c) Cache Yönetimi:

class PostObserver
{
public function saved(Post $post)
{
Cache::tags(['posts'])->flush();
}
}

7. Observer ile Event Farkları:

// Observer Yaklaşımı
class UserObserver
{
public function created(User $user)
{
// İşlemler burada
}
}

// Event Yaklaşımı
class UserCreated
{
public $user;

public function __construct(User $user)
{
$this->user = $user;
}
}

class SendWelcomeEmail
{
public function handle(UserCreated $event)
{
// İşlemler burada
}
}

8. Testing:

class UserObserverTest extends TestCase
{
public function test_profile_is_created_when_user_is_created()
{
$user = User::factory()->create();

$this->assertDatabaseHas('profiles', [
'user_id' => $user->id
]);
}

public function test_notification_is_sent_when_password_changed()
{
Notification::fake();

$user = User::factory()->create();
$user->update(['password' => 'new-password']);

Notification::assertSentTo($user, PasswordChanged::class);
}
}

9. Best Practices:

Single Responsibility:

// Kötü
public function updated(User $user)
{
// Profile güncelle
// Mail gönder
// Cache temizle
// Log tut
}

// İyi
public function updated(User $user)
{
$this->updateProfile($user);
$this->sendNotifications($user);
$this->handleCache($user);
$this->logChanges($user);
}

Error Handling:

public function created(User $user)
{
try {
Profile::create(['user_id' => $user->id]);
} catch (Exception $e) {
Log::error('Profile creation failed', [
'user' => $user->id,
'error' => $e->getMessage()
]);
}
}

Performance Optimization:

public function updated(Post $post)
{
if (!$post->wasChanged()) {
return;
}

Cache::tags(['posts'])->flush();
}

--

--

No responses yet