DEV Community

John Yu
John Yu

Posted on

Design Patterns in Laravel

If you want to code like a pro in Laravel, understanding design patterns is a game-changer. Laravel itself is built on various design patterns, and using them correctly can make your applications more scalable, maintainable, and efficient. Here are some essential Laravel design patterns you need to know:

  1. Singleton Pattern πŸ“Œ Ensures a class has only one instance and provides a global point of access. Use case: When you need a single shared instance, like a logging service, database connection, or configuration settings.

βœ… Example (Service Binding in Laravel)

// AppServiceProvider.php
public function register()
{
$this->app->singleton('App\Services\PaymentGateway', function ($app) {
return new PaymentGateway();
});
}
Why? This ensures that PaymentGateway is only instantiated once and reused throughout the app.

References:

Refactoring Guru β€” Singleton in PHP

Elevating Laravel Development with the Signleton Design Pattern

How to use Laravel’s bind and signleton methods

  1. Repository Pattern πŸ“Œ Decouples database logic from business logic. Use case: Makes it easier to switch between databases or mock data for testing.

βœ… Example (Using a Repository in Laravel)

// Interface
interface UserRepositoryInterface {
public function getAllUsers();
}
// Repository Implementation
class UserRepository implements UserRepositoryInterface {
public function getAllUsers() {
return User::all();
}
}
// Binding in AppServiceProvider
$this->app->bind(UserRepositoryInterface::class, UserRepository::class);
Why? Your controllers only depend on UserRepositoryInterface, so you can swap implementations without modifying business logic.

  1. Factory Pattern πŸ“Œ Creates objects without specifying the exact class to instantiate. Use case: When you need dynamic object creation, such as generating test data or creating models with varying attributes.

βœ… Example (Laravel Model Factories)

// Define in database/factories/UserFactory.php
use Illuminate\Database\Eloquent\Factories\Factory;
class UserFactory extends Factory {
protected $model = User::class;
public function definition() {
return [
'name' => $this->faker->name(),
'email' => $this->faker->unique()->safeEmail(),
'password' => bcrypt('password')
];
}
}
// Use in tests or seeders
User::factory()->count(10)->create();
Why? Automates object creation for testing and seeding without manually writing insert queries.

  1. Strategy Pattern πŸ“Œ Defines a family of algorithms, encapsulates each one, and makes them interchangeable. Use case: Payment gateways, authentication strategies, or data formatting.

βœ… Example (Payment Strategy in Laravel)

interface PaymentStrategy {
public function pay($amount);
}
class PayPalPayment implements PaymentStrategy {
public function pay($amount) {
return "Paid $amount via PayPal";
}
}
class StripePayment implements PaymentStrategy {
public function pay($amount) {
return "Paid $amount via Stripe";
}
}
// Using the strategy
function processPayment(PaymentStrategy $paymentMethod, $amount) {
return $paymentMethod->pay($amount);
}
echo processPayment(new PayPalPayment(), 100);
Why? Allows switching payment providers without modifying core payment logic.

  1. Observer Pattern πŸ“Œ Allows objects to be notified when another object’s state changes. Use case: Email notifications, logging, updating user stats.

βœ… Example (Laravel Event Listeners)

// Event: UserRegistered
class UserRegistered {
public $user;
public function __construct(User $user) {
$this->user = $user;
}
}
// Listener: SendWelcomeEmail
class SendWelcomeEmail {
public function handle(UserRegistered $event) {
Mail::to($event->user->email)->send(new WelcomeEmail());
}
}
// Fire Event
event(new UserRegistered($user));
Why? Decouples the event trigger from the response (e.g., sending an email, logging activity).

  1. Decorator Pattern πŸ“Œ Dynamically adds behavior to objects without modifying their class. Use case: Wrapping existing functionality with extra features, like adding logging to a service.

βœ… Example (Using Middleware in Laravel)

// LoggingMiddleware.php
class LoggingMiddleware {
public function handle($request, Closure $next) {
Log::info("Request made to: " . $request->url());
return $next($request);
}
}
Why? Keeps code modular and applies behavior dynamically without modifying the original request handling.

  1. Facade Pattern πŸ“Œ Provides a static interface to a class while maintaining flexibility. Use case: Simplifies access to complex subsystems, like caching, authentication, or logging.

βœ… Example (Laravel Facade Usage)

use Illuminate\Support\Facades\Cache;
// Store a value
Cache::put('key', 'value', 3600);
// Retrieve value
$value = Cache::get('key');
Why? Facades make complex functionality easily accessible while keeping the underlying implementation flexible.

  1. Command Pattern πŸ“Œ Encapsulates a request as an object, allowing for queuing, logging, and undo mechanisms. Use case: Queue jobs, scheduled tasks, and artisan commands.

βœ… Example (Laravel Queue Jobs)

class SendEmailJob implements ShouldQueue {
public function handle() {
Mail::to('user@example.com')->send(new WelcomeEmail());
}
}
// Dispatch Job
dispatch(new SendEmailJob());
Why? Helps structure background tasks and make them manageable.

Conclusion
Using design patterns in Laravel improves code quality, maintainability, and scalability. Mastering these patterns helps you write professional-grade applications that are modular, testable, and efficient.

πŸš€ Which pattern do you find most useful in your projects?

Heroku

Deploy with ease. Manage efficiently. Scale faster.

Leave the infrastructure headaches to us, while you focus on pushing boundaries, realizing your vision, and making a lasting impression on your users.

Get Started

Top comments (0)

πŸ‘‹ Kindness is contagious

Engage with a wealth of insights in this thoughtful article, valued within the supportive DEV Community. Coders of every background are welcome to join in and add to our collective wisdom.

A sincere "thank you" often brightens someone’s day. Share your gratitude in the comments below!

On DEV, the act of sharing knowledge eases our journey and fortifies our community ties. Found value in this? A quick thank you to the author can make a significant impact.

Okay