<?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();
}
}
<?php
namespace App\Providers;
use App\Models\Post;
use App\Models\User;
use App\Observers\PostObserver;
use App\Observers\UserObserver;
use Illuminate\Foundation\Support\Providers\EventServiceProvider as ServiceProvider;
class EventServiceProvider extends ServiceProvider
{
public function boot(): void
{
Post::observe(PostObserver::class);
User::observe(UserObserver::class);
}
}
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.