Saltar al contenido principal

¿Qué es una facade?

Una facade proporciona una interfaz “estática” a las clases disponibles en el contenedor de servicios de la aplicación. Laravel incluye numerosas facades que dan acceso a casi todas sus funcionalidades. Las facades de Laravel funcionan como “proxies estáticos” sobre las clases reales del contenedor y ofrecen una sintaxis concisa y expresiva manteniendo mejor testabilidad y flexibilidad que los métodos estáticos tradicionales. Todas las facades de Laravel están en el namespace Illuminate\Support\Facades.
use Illuminate\Support\Facades\Cache;
use Illuminate\Support\Facades\Route;

Route::get('/cache', function () {
    return Cache::get('key');
});
No pasa nada si aún no comprendes por completo su funcionamiento. Empieza por aprender a usarlas y continúa aprendiendo Laravel.

Cómo funciona una facade

En una aplicación Laravel, una facade es una clase que da acceso a un objeto del contenedor. Este mecanismo se implementa con la clase Facade. Todas las facades de Laravel y las tuyas propias extienden la clase base Illuminate\Support\Facades\Facade. La clase base Facade utiliza el método mágico __callStatic() para delegar las llamadas a la facade al objeto resuelto desde el contenedor.
<?php

namespace App\Http\Controllers;

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

class UserController extends Controller
{
    /**
     * Muestra el perfil del usuario indicado
     */
    public function showProfile(string $id): View
    {
        $user = Cache::get('user:'.$id);

        return view('profile', ['user' => $user]);
    }
}
Importamos la fachada Cache en la parte superior del archivo. Esa fachada actúa como proxy hacia una implementación de la interfaz Illuminate\Contracts\Cache\Factory. Todas las llamadas a través de la fachada se pasan a la instancia interna del servicio de caché de Laravel. Si miras la clase Illuminate\Support\Facades\Cache, verás que no existe el método estático get.
class Cache extends Facade
{
    /**
     * Obtiene el nombre registrado del componente
     */
    protected static function getFacadeAccessor(): string
    {
        return 'cache';
    }
}
Cache extiende la clase base Facade y define getFacadeAccessor(). Este método devuelve el nombre del binding en el contenedor. Cuando llamas a un método estático de Cache, Laravel resuelve el binding cache del contenedor y ejecuta el método solicitado (get en este caso) sobre el objeto obtenido.

Cuándo usar facades y cuándo no

Ventajas de las facades

Ofrecen una sintaxis concisa y fácil de recordar para usar las funcionalidades de Laravel, sin necesidad de recordar los nombres de clase largos que habría que inyectar o configurar manualmente. Además, gracias al uso particular de los métodos dinámicos de PHP, son fáciles de probar.

Cuidado con el crecimiento del ámbito

Un peligro habitual al usar facades es la “acumulación de responsabilidades” en la clase. Como son cómodas y no requieren inyección, es fácil que la clase se hinche usando muchas facades. Con la inyección de dependencias, un constructor grande te avisa visualmente. Al usar facades, mantén las clases pequeñas y con responsabilidad acotada.
Si notas que una clase crece demasiado, considera dividirla en clases más pequeñas.

Facades vs. inyección de dependencias

Una gran ventaja de la inyección de dependencias es poder sustituir la implementación inyectada. Es útil en las pruebas: puedes inyectar mocks o stubs y comprobar qué métodos se han llamado sobre ellos. Los métodos estáticos “puros” no se pueden mockear normalmente, pero las facades sí, ya que redirigen las llamadas al objeto del contenedor mediante métodos dinámicos. Se pueden probar como si se tratara de una instancia inyectada.
use Illuminate\Support\Facades\Cache;

Route::get('/cache', function () {
    return Cache::get('key');
});
Para esta ruta puedes escribir la siguiente prueba comprobando que Cache::get se llama con los argumentos esperados.
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. funciones helper

Además de las facades, Laravel ofrece funciones “helper” para tareas comunes: crear vistas, disparar eventos, despachar jobs, enviar respuestas HTTP, etc. Muchas hacen lo mismo que la facade correspondiente.
// Llamada usando la fachada
return Illuminate\Support\Facades\View::make('profile');

// Llamada equivalente con función helper
return view('profile');
No hay diferencia sustancial entre facades y helpers. Aunque uses helpers, puedes hacer las mismas pruebas que con las facades.
use Illuminate\Support\Facades\Cache;

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

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

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

Facades en tiempo real

Con las facades en tiempo real, puedes tratar cualquier clase de tu aplicación como una fachada. Veamos primero un ejemplo sin usarlas. Supón que el modelo Podcast tiene un método publish. Para publicar el podcast necesita una instancia de Publisher.
<?php

namespace App\Models;

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

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

        $publisher->publish($this);
    }
}
Con una facade en tiempo real puedes mantener la misma testabilidad sin tener que pasar explícitamente la instancia de Publisher. Para crearla, añade el prefijo Facades al namespace de la clase que importas.
<?php

namespace App\Models;

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

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

        Publisher::publish($this);
    }
}
Cuando se usa una facade en tiempo real, la implementación se resuelve desde el contenedor usando la parte de interfaz o clase que aparece después del prefijo Facades.
<?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();
});
Las facades en tiempo real son útiles cuando quieres poder mockear en pruebas sin tener que pasar dependencias como argumentos.

Cómo probar facades

Para probar una facade usa shouldReceive, que devuelve una instancia mock de Mockery. Como las facades se resuelven y gestionan a través del contenedor, son mucho más fáciles de probar que los métodos estáticos habituales.
use Illuminate\Support\Facades\Cache;

test('mostrar el perfil del usuario', function () {
    Cache::shouldReceive('get')
        ->once()
        ->with('user:1')
        ->andReturn(['name' => 'Taylor']);

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

    $response->assertSee('Taylor');
});
Métodos habituales del mock:
MétodoDescripción
shouldReceive('method')Se espera que se llame al método
once()Se espera una única llamada
times(n)Se esperan n llamadas
with(args)Se espera que se llame con estos argumentos
andReturn(value)Devuelve el valor indicado
andReturnNull()Devuelve null

Lista de facades principales

Tabla de facades habituales, sus clases reales y sus bindings en el contenedor.
FacadeClaseBinding
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

Próximos pasos

Contracts (contratos)

Aprende sobre los Contracts, la contraparte conceptual de las facades, y cuándo elegir uno u otro.
Última modificación el 13 de julio de 2026