¿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 namespaceIlluminate\Support\Facades.
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 claseFacade. 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.
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.
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.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.Cache::get se llama con los argumentos esperados.
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.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 modeloPodcast tiene un método publish. Para publicar el podcast necesita una instancia de Publisher.
Publisher. Para crearla, añade el prefijo Facades al namespace de la clase que importas.
Facades.
Cómo probar facades
Para probar una facade usashouldReceive, 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.
| Método | Descripció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.| Facade | Clase | Binding |
|---|---|---|
App | Illuminate\Foundation\Application | app |
Auth | Illuminate\Auth\AuthManager | auth |
Cache | Illuminate\Cache\CacheManager | cache |
Config | Illuminate\Config\Repository | config |
Cookie | Illuminate\Cookie\CookieJar | cookie |
Crypt | Illuminate\Encryption\Encrypter | encrypter |
DB | Illuminate\Database\DatabaseManager | db |
Event | Illuminate\Events\Dispatcher | events |
File | Illuminate\Filesystem\Filesystem | files |
Gate | Illuminate\Contracts\Auth\Access\Gate | — |
Hash | Illuminate\Contracts\Hashing\Hasher | hash |
Http | Illuminate\Http\Client\Factory | — |
Log | Illuminate\Log\LogManager | log |
Mail | Illuminate\Mail\Mailer | mailer |
Notification | Illuminate\Notifications\ChannelManager | — |
Queue | Illuminate\Queue\QueueManager | queue |
RateLimiter | Illuminate\Cache\RateLimiter | — |
Redirect | Illuminate\Routing\Redirector | redirect |
Request | Illuminate\Http\Request | request |
Route | Illuminate\Routing\Router | router |
Schema | Illuminate\Database\Schema\Builder | — |
Session | Illuminate\Session\SessionManager | session |
Storage | Illuminate\Filesystem\FilesystemManager | filesystem |
URL | Illuminate\Routing\UrlGenerator | url |
Validator | Illuminate\Validation\Factory | validator |
View | Illuminate\View\Factory | view |
Próximos pasos
Contracts (contratos)
Aprende sobre los Contracts, la contraparte conceptual de las facades, y cuándo elegir uno u otro.