Facade (Laravel) — the static proxy over a container-resolved instance
Definition
A Facade in Laravel is a static proxy that provides a static-style interface to an object resolved from the service container. When you call Cache::get('key'), PHP routes the static call to __callStatic() on the Cache facade class, which retrieves the real cache object from the container and forwards the call to it. The underlying object is not static — it is a fully injectable, testable, container-managed instance. The Facade is a syntactic convenience, not a pattern that bypasses the container.
In Practice
<?php
// Using the Facade — looks static, but isn't
use Illuminate\Support\Facades\Cache;
use Illuminate\Support\Facades\DB;
Cache::put('user:1', $userData, ttl: 3600);
$user = Cache::get('user:1');
// What happens internally (simplified):
// Cache::__callStatic('get', ['user:1'])
// → Cache::getFacadeRoot() // retrieves from container
// → app('cache') // the real CacheManager instance
// → $cacheManager->get('user:1') // actual method call
// Real-time facades — turn any class into a Facade on the fly
// Prefix the namespace with Facades\
use Facades\App\Services\PaymentService;
PaymentService::charge($amount); // no explicit binding needed
// Testing facades — swappable because the underlying object is container-managed
Cache::fake(); // replaces the real driver with an array store
Cache::shouldReceive('put')->once()->with('user:1', $userData, 3600);In a Laravel codebase, Facades appear wherever a team prefers the concise static syntax over constructor injection. Log::info(), Route::get(), Event::dispatch(), Auth::user() — all Facades. The getFacadeAccessor() method on each Facade class returns the container key used to resolve the underlying instance.
In Context
In interviews, the key insight examiners want is: Facade calls are not actually static. They are syntactic sugar over container resolution. This means Facades are testable (via Facade::fake() and Facade::shouldReceive()), swappable (change the binding in the container, all Facades using that key change too), and not global state in the traditional sense — they are scoped to the container's lifecycle.
The design pattern the Laravel Facade implements is not the GoF Facade pattern (which simplifies a complex subsystem). It is closer to the Proxy pattern — intercepting calls and forwarding them to a real object. Laravel's use of the word "Facade" is technically a misnomer compared to the GoF definition, which is worth knowing if an interviewer asks you to distinguish them.
The trade-off versus constructor injection: Facades are convenient but obscure dependencies. A class using Cache::get() in its body does not declare CacheStore as a dependency in its constructor, making it harder to see what the class actually needs and harder to test by providing a different cache implementation. Many Laravel teams adopt a style guide that requires Facades only in service providers and configuration code, and constructor injection everywhere else.