مقاله

created، updated، deleted و registering observer — چه زمانی Observer به‌جای Event class و چطور از حلقه بی‌نهایت جلوگیری کنیم.

Observer در Laravel — رویدادهای مدل Eloquent به‌درستی

Observer در Laravel — رویدادهای مدل Eloquent به‌درستی

Post ذخیره شد → cache homepage پاک شود، sitemap بسازد، slug redirect ثبت شود. این کارها نباید در Controller پخش شوند — Observer (یا Event) نقطه متمرکز side effect است. در همین پورتفولیو PostObserver همین نقش را دارد.

Observer vs Event/Listener

  • Observer — وابسته به lifecycle یک Model مشخص
  • Event — domain event گسترده‌تر، چند listener، queue

برای «بعد از save Post» Observer کافی؛ برای «OrderPaid» با چند سرویس Event بهتر است.

ساخت Observer

php artisan make:observer PostObserver --model=Post
class PostObserver
{
    public function creating(Post $post): void
    {
        if (empty($post->slug)) {
            $post->slug = Str::slug($post->title);
        }
    }

    public function saved(Post $post): void
    {
        Cache::forget('homepage.posts');
    }

    public function deleted(Post $post): void
    {
        // cleanup media relations
    }
}

ثبت Observer

// AppServiceProvider boot — یا Post::observe در booted model
Post::observe(PostObserver::class);

Laravel 11+ اغلب در AppServiceProvider یا با attribute.

رویدادهای lifecycle

retrieving، creating، created، updating، updated، saving، saved، deleting، deleted، restoring، restored، replicating.

creating/updating — قبل از insert/update — می‌توانید mutate یا return false برای cancel.

created/updated — بعد از commit در DB.

saved vs updated

saved هر create و update؛ updated فقط update. برای cache clear اغلب saved کافی است.

جلوگیری از حلقه بی‌نهایت

public function saved(Post $post): void
{
    if ($post->wasChanged('views')) {
        return; // فقط views عوض شد — cache لازم نیست
    }
    Cache::forget('homepage.posts');
}

یا $post->saveQuietly() بدون firing events.

Observer و Queue

کار سنگین را در listener queue کنید — Observer سبک بماند. mail سنگین در created بدون queue request را کند می‌کند.

تست Observer

Event::fake([/* اگر event dispatch می‌کنید */]);
Post::factory()->create();
Cache::shouldHaveReceived('forget');

boot method در Model

برای logic کوتاه:

protected static function booted(): void
{
    static::creating(function (Post $post) {
        $post->user_id ??= auth()->id();
    });
}

Observer وقتی class بزرگ می‌شود تمیزتر است.

اشتباهات

  • منطق کسب‌وکار سنگین در Observer
  • save دوباره در saved بدون quiet
  • فراموش کردن تفاوت local vs production side effect

جمع‌بندی

Observer برای side effect نزدیک به persistence. business logic در Service. با cast و scope مدل کامل می‌شود.

معماری event-driven