Facades in Laravel are built on the Facade Design Pattern - a structural design pattern that provides a simplified interface to a more complex system of classes or logic behind the scenes.
Think of it like using a TV remote control:
Instead of interacting with each internal component of the TV - like the tuner, speakers, power module, or HDMI switch - you simply press buttons on the remote. The remote (the facade) provides a simple, unified interface to control a complex system behind the scenes.
The Facade Pattern – A Quick Overview
- Origin: One of the classic Gang of Four (GoF) design patterns.
- Purpose: Simplifies access to a complex system by exposing only essential parts.
- Behavior: Wraps internal logic without altering or replacing it.
- Benefit: Results in cleaner code, reduced coupling, and improved maintainability.
Laravel Facades
Laravel facades use this pattern to make things easier - they let you call complex services in a simple, static way, while still working with Laravel’s powerful service container behind the scenes.
For example, the following line is actually resolving the CacheManager
service from Laravel's service container behind the scenes:
Cache::put('key', 'value', 600);
Why Use Facades
- To provide a simplified, static-like interface to complex logic.
- To keep the underlying classes testable and mockable.
- To avoid manually injecting dependencies throughout your application.
What We'll Build
We'll create a CurrencyConverter
service that converts amounts between currencies. Then, we'll expose it via a Currency
facade, allowing usage like this:
use App\Facades\Currency; $amount = Currency::convert(100, 'USD', 'EUR');
Let's get started.
Step 1: Create a Service Class
Create a dedicated class that contains your business logic. In this case, we'll create CurrencyConverterService
inside app/Services
.
<?php declare(strict_types=1); namespace App\Services; final class CurrencyConverterService{ /** * Convert a monetary amount from one currency to another. */ public function convert(float $amount, string $from, string $to): float { if ($amount < 0) { /** * @todo throw proper exceptions and handle accordingly * eg. throw new InvalidArgumentException('Amount must be non-negative.'); */ } $rate = $this->getExchangeRate($from, $to); return round($amount * $rate, 2); } /** * Get the exchange rate between two currencies. */ private function getExchangeRate(string $from, string $to): float { /** * API call for actual exchange rates */ $rates = [ 'USD_EUR' => 0.91, 'EUR_USD' => 1.10, ]; $key = mb_strtoupper("{$from}_{$to}"); if (! array_key_exists($key, $rates)) { /** * @todo throw proper exceptions and handle accordingly */ return 1.0; } return $rates[$key]; }}
Step 2: Bind It to Laravel's Service Container
Bind the service class in a provider.
a. Create a new service provider:
php artisan make:provider CurrencyServiceProvider
b. Register the service in the register()
method:
<?php declare(strict_types=1); namespace App\Providers; use App\Services\CurrencyConverterService;use Illuminate\Support\ServiceProvider; final class CurrencyServiceProvider extends ServiceProvider{ /** * Register services. */ public function register(): void { $this->app->singleton(CurrencyConverterService::class, fn () => new CurrencyConverterService()); } /** * Bootstrap services. */ public function boot(): void {}}
c. Register the provider:
In bootstrap/providers.php
, add your provider if it hasn't been added automatically:
<?php return [ App\Providers\AppServiceProvider::class, App\Providers\CurrencyServiceProvider::class,];
If you used Artisan to create the provider, it may already be registered.
Step 3: Create the Facade Class
Create the facade class inside app/Facades
. Laravel facades must extend Illuminate\Support\Facades\Facade
.
<?php declare(strict_types=1); namespace App\Facades; use App\Services\CurrencyConverterService;use Illuminate\Support\Facades\Facade; final class Currency extends Facade{ protected static function getFacadeAccessor(): string { return CurrencyConverterService::class; }}
Internally,
Currency::convert()
proxies the call to the bound service. ThegetFacadeAccessor()
tells Laravel which class or binding to resolve from the container.
Step 4: Use the Facade
use App\Facades\Currency; $converted = Currency::convert(100, 'USD', 'EUR'); dd($converted);
Conclusion
Creating custom facades in Laravel offers a clean and expressive way to abstract complex logic behind a unified interface. By leveraging Laravel's service container and the Facade pattern, you can build code that is both intuitive to use and easy to maintain. Whether you're wrapping a simple utility class or a more complex service, facades help promote separation of concerns and improve the DX across your application.

Detail-oriented Backend Engineer dedicated to building high-quality applications.