Courses Developer Fundamentals for Builders Design Patterns in the Wild

PHP and Object-Oriented Programming

Design Patterns in the Wild

Patterns you use every day without knowing their names

11 min read · Lesson 9 of 18

You Already Use Design Patterns

Design patterns are named solutions to recurring problems. You don't need to memorize the Gang of Four book, but recognizing the patterns Laravel uses helps you understand why the framework is structured the way it is — and when to apply the same patterns in your own code.


Facade Pattern

When you write Cache::get('key') or DB::table('users'), you're using the Facade pattern. A facade provides a static-like interface to an object resolved from the service container.

Cache isn't a class with a static get() method. It's a facade that:

  1. Intercepts the static call via PHP's __callStatic() magic method.
  2. Resolves the underlying cache manager from the service container.
  3. Forwards the method call to the resolved instance.

Facades are syntactic sugar for dependency injection. Cache::get('key') is equivalent to app('cache')->get('key'). They're convenient but hide dependencies — in service classes, prefer injecting the actual interface.


Observer Pattern

Laravel's event system is the Observer pattern. Objects emit events; listeners observe and react to those events:

// Dispatching an event
OrderPlaced::dispatch($order);

// Listening (in EventServiceProvider)
OrderPlaced::class => [
    SendConfirmationEmail::class,
    UpdateInventory::class,
    NotifyWarehouse::class,
]

Eloquent model events (creating, updating, deleting) are also Observer pattern implementations. The Observer class you can generate with php artisan make:observer hooks into model lifecycle events.


Strategy Pattern

The Strategy pattern defines a family of algorithms and makes them interchangeable. In Laravel:

  • Cache drivers — File, Redis, Memcached, Database. Same interface, different strategies.
  • Queue drivers — Sync, Database, Redis, SQS.
  • Mail drivers — SMTP, Postmark, SES, Mailgun.
  • Session drivers — File, Cookie, Database, Redis.

Each driver implements the same interface but uses a different algorithm. You switch strategies by changing a config value — your application code doesn't change at all.


Builder Pattern

The Builder pattern constructs complex objects step by step. Laravel's query builder is the classic example:

$users = DB::table('users')
    ->where('active', true)
    ->where('role', 'admin')
    ->orderBy('name')
    ->limit(10)
    ->get();

Each method call returns the builder itself (method chaining), adding a constraint to the query being constructed. The get() call at the end triggers execution. Eloquent's query scopes follow the same pattern.


Key Takeaways

  • Facades provide static-like access to container-resolved objects. Convenient but hide dependencies.
  • Observer (Events/Listeners) decouples actions from reactions. Use it when multiple things should happen in response to one event.
  • Strategy makes algorithms interchangeable. Every Laravel driver system uses this pattern.
  • Builder constructs complex objects step by step. The query builder and Eloquent scopes are prime examples.
Ask about this lesson