Laravel model observers for lifecycle hooks

Carlos Mendez Jan 2026
2 tabs
<?php

namespace App\Observers;

use App\Events\PostPublished;
use App\Models\Post;
use Illuminate\Support\Facades\Cache;
use Illuminate\Support\Str;

class PostObserver
{
    public function creating(Post $post): void
    {
        // Auto-generate slug before creating
        if (empty($post->slug)) {
            $post->slug = Str::slug($post->title);
        }

        // Set excerpt if not provided
        if (empty($post->excerpt)) {
            $post->excerpt = Str::limit(strip_tags($post->body), 200);
        }
    }

    public function created(Post $post): void
    {
        // Log post creation
        \Log::info("Post created: {$post->title}", ['id' => $post->id]);

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

    public function updating(Post $post): void
    {
        // Check if being published
        if ($post->isDirty('published_at') && $post->published_at) {
            event(new PostPublished($post));
        }
    }

    public function updated(Post $post): void
    {
        // Clear specific post cache
        Cache::forget("post:{$post->id}");
        Cache::tags(['posts'])->flush();
    }

    public function deleting(Post $post): bool
    {
        // Prevent deletion if post has comments
        if ($post->comments()->exists()) {
            return false;
        }

        // Delete related data
        $post->tags()->detach();

        return true;
    }

    public function deleted(Post $post): void
    {
        Cache::tags(['posts'])->flush();
        \Log::warning("Post deleted: {$post->title}", ['id' => $post->id]);
    }

    public function restored(Post $post): void
    {
        Cache::tags(['posts'])->flush();
    }
}
2 files · php Explain with highlit

Observers consolidate model event listeners in dedicated classes, preventing bloated models. Each observer method corresponds to an Eloquent event—creating, created, updating, updated, deleting, deleted. I register observers in boot() methods of service providers. Observers handle side effects like logging, cache invalidation, or triggering notifications. The creating event modifies attributes before saving. Observers can prevent actions by returning false from events. For multiple models sharing behavior, I create abstract observers. This pattern separates concerns—models define structure, observers handle reactions. It's cleaner than cluttering models with event callbacks.