What a Facade is — the static proxy pattern in Laravel
Concept
A Facade in Laravel is a class that provides a static interface to a service in the IoC container. Cache::get('key') looks like a static method call, but it's actually resolved from the container and called on an instance.
The problem Facades solve: Dependency injection requires passing services through constructors. In views, route closures, config files, and other places where you don't control construction, accessing container-bound services via static syntax is more ergonomic.
Facades are NOT global functions: They're proxy classes. Cache::get('key') resolves the cache binding from the container and calls ->get('key') on the instance. IDE type hints work via @method annotations in Laravel's IDE helper package.
The static proxy pattern: Every Facade extends Illuminate\Support\Facades\Facade. The only required method is getFacadeAccessor() — it returns the container binding key. When a static method is called on the Facade, __callStatic resolves the accessor from the container and forwards the call.
Facade vs. helper functions: cache() and Cache::get() do the same thing. Helpers are syntactic sugar. Facades are classes. Both resolve from the container. Use whichever is more readable in context. For type safety and IDE support, some teams prefer always injecting via constructor.
Real facades vs fake facades: In tests, Cache::fake() / Cache::spy() / Cache::shouldReceive() replace the container binding with a mock. This is why Facades are more testable than true static classes.
Code Example
<?php
// Using Facades — the common way
use Illuminate\Support\Facades\Cache;
use Illuminate\Support\Facades\Log;
use Illuminate\Support\Facades\DB;
use Illuminate\Support\Facades\Route;
Cache::put('key', 'value', 3600);
$value = Cache::get('key');
Log::info('User logged in', ['user_id' => 1]);
$users = DB::table('users')->where('active', 1)->get();
// Facades resolve from the container
// Cache::get() === app('cache')->get() === app()->make(CacheManager::class)->get()
// Helper function equivalents (same result)
cache()->put('key', 'value', 3600);
cache(['key' => 'value'], 3600); // shorter syntax
$value = cache('key');
// All Facades available in Laravel
// Auth, Blade, Broadcast, Bus, Cache, Config, Cookie
// Crypt, DB, Eloquent, Event, File, Gate, Hash, Http
// Lang, Log, Mail, Notification, Password, Queue
// Redirect, Response, Route, Schema, Session, Storage
// URL, Validator, View
// Checking what a Facade resolves to
Cache::getFacadeRoot(); // returns the underlying CacheManager instance
get_class(Cache::getFacadeRoot()); // "Illuminate\Cache\CacheManager"
// Facade alias (from config/app.php aliases array)
// 'Cache' => Illuminate\Support\Facades\Cache::class
// This is why you can use Cache without full namespace in many files