Skip to main content

What are facades

Facades provide a “static” interface to classes that are available in your application’s service container. Laravel ships with many facades that provide access to almost all of its features. Laravel facades serve as “static proxies” to underlying classes in the service container, providing the benefit of a terse, expressive syntax while maintaining more testability and flexibility than traditional static methods. All of Laravel’s facades are defined in the Illuminate\Support\Facades namespace.
use Illuminate\Support\Facades\Cache;
use Illuminate\Support\Facades\Route;

Route::get('/cache', function () {
    return Cache::get('key');
});
Don’t worry about fully understanding how facades work at this point. Just learn how to use them and continue learning Laravel.

How facades work

In a Laravel application, a facade is a class that provides access to an object from the container. The machinery that makes this work is in the Facade class. Laravel’s facades—and any custom facades you create—will extend the base Illuminate\Support\Facades\Facade class. The Facade base class makes use of the __callStatic() magic method to defer calls from your facade to an object resolved from the container.
<?php

namespace App\Http\Controllers;

use Illuminate\Support\Facades\Cache;
use Illuminate\View\View;

class UserController extends Controller
{
    /**
     * Show the profile for the given user.
     */
    public function showProfile(string $id): View
    {
        $user = Cache::get('user:'.$id);

        return view('profile', ['user' => $user]);
    }
}
At the top of the file, we import the Cache facade. This facade serves as a proxy for accessing the underlying implementation of the Illuminate\Contracts\Cache\Factory interface. Any calls we make using the facade will be passed to the underlying instance of Laravel’s cache service. If we look at the Illuminate\Support\Facades\Cache class, you’ll see that there is no static method get:
class Cache extends Facade
{
    /**
     * Get the registered name of the component.
     */
    protected static function getFacadeAccessor(): string
    {
        return 'cache';
    }
}
The Cache facade extends the base Facade class and defines the getFacadeAccessor() method. This method returns the name of a service container binding. When a user references any static method on the Cache facade, Laravel resolves the cache binding from the service container and runs the requested method (in this case, get) against that object.

When to use, and when not to use, facades

The benefits of facades

Facades have many benefits. They provide a terse, memorable syntax that lets you use Laravel’s features without having to remember long class names that must be injected or configured manually. Because of PHP’s unique usage of dynamic methods, they are also very easy to test.

Beware of scope creep

The primary risk of using facades is class “scope creep.” Since facades are easy to use and don’t require injection, it’s easy to let your classes grow and continue to use many facades in a single class. Using dependency injection, this potential is mitigated by the visual feedback a large constructor gives you. So, when using facades, pay special attention to the size of your class so that its scope of responsibility stays narrow.
If you feel your class is getting too large, consider splitting it into multiple smaller classes.

Facades vs. dependency injection

One of the primary benefits of dependency injection is the ability to swap implementations of the injected class. This is useful during testing, since you can inject a mock or stub and assert that various methods were called on the stub. Typically, it would not be possible to mock or stub a truly static class method. However, because facades use dynamic methods to proxy method calls to objects resolved from the service container, you can test facades just as you would test an injected class instance.
use Illuminate\Support\Facades\Cache;

Route::get('/cache', function () {
    return Cache::get('key');
});
For this route, you could write the following test to verify that Cache::get was called with the argument we expected:
use Illuminate\Support\Facades\Cache;

test('basic example', function () {
    Cache::shouldReceive('get')
        ->with('key')
        ->andReturn('value');

    $response = $this->get('/cache');

    $response->assertSee('value');
});

Facades vs. helper functions

In addition to facades, Laravel provides a variety of “helper” functions that can perform common tasks like generating views, firing events, dispatching jobs, or sending HTTP responses. Many of these helper functions perform the same function as a corresponding facade.
// Call using the facade
return Illuminate\Support\Facades\View::make('profile');

// Equivalent call using the helper function
return view('profile');
There is no practical difference between facades and helper functions. When using helper functions, you can still test them exactly as you would the corresponding facade.
use Illuminate\Support\Facades\Cache;

test('cache helper test', function () {
    Cache::shouldReceive('get')
        ->with('key')
        ->andReturn('value');

    $response = $this->get('/cache');

    $response->assertSee('value');
});

Real-time facades

Using real-time facades, you may treat any class in your application as if it were a facade. To illustrate how this can be used, let’s first examine some code that does not use real-time facades. For example, let’s assume our Podcast model has a publish method. However, in order to publish the podcast, we need to inject a Publisher instance.
<?php

namespace App\Models;

use App\Contracts\Publisher;
use Illuminate\Database\Eloquent\Model;

class Podcast extends Model
{
    /**
     * Publish the podcast.
     */
    public function publish(Publisher $publisher): void
    {
        $this->update(['publishing' => now()]);

        $publisher->publish($this);
    }
}
Using real-time facades, we can maintain the same testability while not being required to explicitly pass a Publisher instance. To generate a real-time facade, prefix the namespace of the imported class with Facades.
<?php

namespace App\Models;

use Facades\App\Contracts\Publisher;
use Illuminate\Database\Eloquent\Model;

class Podcast extends Model
{
    /**
     * Publish the podcast.
     */
    public function publish(): void
    {
        $this->update(['publishing' => now()]);

        Publisher::publish($this);
    }
}
When the real-time facade is used, the publisher implementation will be resolved from the service container using the portion of the interface or class name that appears after the Facades prefix.
<?php

use App\Models\Podcast;
use Facades\App\Contracts\Publisher;
use Illuminate\Foundation\Testing\RefreshDatabase;

pest()->use(RefreshDatabase::class);

test('podcast can be published', function () {
    $podcast = Podcast::factory()->create();

    Publisher::shouldReceive('publish')->once()->with($podcast);

    $podcast->publish();
});
Real-time facades are useful when you want to keep tests easy to mock while removing the need to pass the dependency as an argument.

Testing facades

To test a facade, use the shouldReceive method, which returns a Mockery mock instance. Because facades are actually resolved and managed by the service container, they’re far more testable than typical static classes.
use Illuminate\Support\Facades\Cache;

test('display user profile', function () {
    Cache::shouldReceive('get')
        ->once()
        ->with('user:1')
        ->andReturn(['name' => 'Taylor']);

    $response = $this->get('/users/1');

    $response->assertSee('Taylor');
});
Commonly used mock methods:
MethodDescription
shouldReceive('method')Expect the method to be called
once()Expect it to be called exactly once
times(n)Expect it to be called n times
with(args)Expect it to be called with specific arguments
andReturn(value)Return the given value
andReturnNull()Return null

Key facades reference

A mapping of commonly used facades to their underlying classes and service container bindings:
FacadeClassBinding
AppIlluminate\Foundation\Applicationapp
AuthIlluminate\Auth\AuthManagerauth
CacheIlluminate\Cache\CacheManagercache
ConfigIlluminate\Config\Repositoryconfig
CookieIlluminate\Cookie\CookieJarcookie
CryptIlluminate\Encryption\Encrypterencrypter
DBIlluminate\Database\DatabaseManagerdb
EventIlluminate\Events\Dispatcherevents
FileIlluminate\Filesystem\Filesystemfiles
GateIlluminate\Contracts\Auth\Access\Gate
HashIlluminate\Contracts\Hashing\Hasherhash
HttpIlluminate\Http\Client\Factory
LogIlluminate\Log\LogManagerlog
MailIlluminate\Mail\Mailermailer
NotificationIlluminate\Notifications\ChannelManager
QueueIlluminate\Queue\QueueManagerqueue
RateLimiterIlluminate\Cache\RateLimiter
RedirectIlluminate\Routing\Redirectorredirect
RequestIlluminate\Http\Requestrequest
RouteIlluminate\Routing\Routerrouter
SchemaIlluminate\Database\Schema\Builder
SessionIlluminate\Session\SessionManagersession
StorageIlluminate\Filesystem\FilesystemManagerfilesystem
URLIlluminate\Routing\UrlGeneratorurl
ValidatorIlluminate\Validation\Factoryvalidator
ViewIlluminate\View\Factoryview

Next steps

Contracts

Learn about Contracts and how they complement facades.
Last modified on July 13, 2026