Facades


brief introduction

Note: Do you understand the concept of facade? Reference PHP Design Pattern Series - Facade
The door surface is applied Service Container The binding class in provides a "static" interface. Larave has many built-in facades, and you may be using them without knowing it. As the "static proxy" of the underlying class in the service container, Laravel's facade can provide more easily tested, flexible, concise and elegant syntax when maintaining compared with traditional static methods.

All the facades of Laravel are defined in Illuminate\Support\Facades Namespaces, so we can easily access the facade:

 use Illuminate\Support\Facades\Cache; Route::get('/cache', function () { return Cache::get('key'); });

In the entire Larravel document, many examples use the facade to demonstrate the various functional features of the framework.

When to use the facade

Facade has many advantages. It provides simple and easy to remember syntax, so that we can use the functional features provided by Laravel without having to remember long class names. In addition, because of their unique use of PHP dynamic methods, they are easy to test.

However, the use of facade also needs attention. One of the main dangers is class scope creep. Because facades are so easy to use and do not need injection, using too many facades in a single class will easily make the class become larger and larger. Using dependency injection will ease this problem, because a huge constructor will make it easy to determine that the class is getting larger. Therefore, when using the facade, pay special attention to the size of the class in order to control its limited responsibilities.

Note: When building a third-party expansion package that interacts with Larvel, it is better to inject Larvel contract Instead of using facade, because the expansion package is built outside of Laravel, you will not be able to access Laravel's facade test auxiliary functions.

Facade vs. Dependency Injection

The biggest advantage of dependency injection is that you can replace the implementation of injected classes, which is very useful in testing, because you can inject a simulation or stub and assert different methods on the stub.

However, it is not feasible to simulate or stub static class methods. However, because the facade uses dynamic methods to proxy the object method calls resolved in the service container, we can also test the facade like testing injected class instances. For example, given the following route:

 use Illuminate\Support\Facades\Cache; Route::get('/cache', function () { return Cache::get('key'); });

We can write tests to verify Cache::get The method is called in the way we expect:

 use Illuminate\Support\Facades\Cache; /** * A basic functional test example. * * @return void */ public function testBasicExample() { Cache::shouldReceive('get') ->with('key') ->andReturn('value'); $this->visit('/cache') ->see('value'); }

Facade vs auxiliary function

In addition to the facade, Larravel also has many built-in auxiliary functions to perform common tasks, such as generating views, triggering events, assigning tasks, and sending HTTP responses. Many auxiliary functions provide the same function as the corresponding facade. For example, the following facade call is equivalent to the auxiliary function call:
 return View::make('profile'); return view('profile');
There is no substantial difference between the facade and auxiliary functions. When using auxiliary functions, you can test them as you test the corresponding facade. For example, given the following route:
 Route::get('/cache', function () { return cache('key'); });
At the bottom of the call, cache Method will call Cache On the facade get Therefore, although we use this auxiliary function, we can still write the following test to verify that this method is called in the way we expect and with parameters:
 use Illuminate\Support\Facades\Cache; /** * A basic functional test example. * * @return void */ public function testBasicExample() { Cache::shouldReceive('get') ->with('key') ->andReturn('value'); $this->visit('/cache') ->see('value'); }

Working principle of door surface

In Laravel applications, facade is a class that provides access methods for objects in containers. The principle of this mechanism is Facade Class implementation. The built-in facade of Larravel and the customized facade we created will be inherited from Illuminate\Support\Facades\Facade Base class.

The facade class only needs to implement one method: getFacadeAccessor Exactly getFacadeAccessor Method defines what to parse from the container, and then Facade The base class uses magic methods __callStatic() Call the resolution object from your facade.

In the following example, we will call Larave's cache system. After browsing the code, you may think that we have called Cache Static methods for get

 <? php namespace App\Http\Controllers; use Cache; use App\Http\Controllers\Controller; class UserController extends Controller{ /** *Display properties for the specified user * * @param  int  $id * @return Response */ public function showProfile($id) { $user = Cache::get('user:'.$id); return view('profile', ['user' => $user]); } }

Notice that we introduced the Cache Facade. This facade accesses the bottom layer as a proxy Illuminate\Contracts\Cache\Factory Implementation of the interface. All our calls to the facade will be passed to the underlying instance of the Laravel cache service.

If we check Illuminate\Support\Facades\Cache Class source code, you will find that there is no static method get

 class Cache extends Facade { /** *Get component registration name * * @return string */ protected static function getFacadeAccessor() {  return 'cache';  } }

Cache Facade inheritance Facade Base class and defined getFacadeAccessor Method. The job of this method is to return the alias of the service container binding class. When the user references Cache Class Service Container Medium resolution cache Bind, and then call all request methods on the parsed object (in this case get )。

Real time facade

With real-time facade, you can use any class in the application as a facade. To illustrate how to use this function, let's first look at an alternative solution. For example, we assume that Podcast The model has a publish However, in order to publish a blog, we need to inject Publisher example:
 <? php namespace App; use App\Contracts\Publisher; use Illuminate\Database\Eloquent\Model; class Podcast extends Model { /** * Publish the podcast. * * @param   Publisher  $publisher * @return void */ public function publish(Publisher $publisher) { $this->update(['publishing' => now()]); $publisher->publish($this); } }

Because the injected publishing service can be simulated, we can easily test the method in isolation after the injection publishing is implemented to the method. However, this requires that we call publish All methods need to pass a publishing service instance. Using the real-time facade, we can maintain the ease of testing without explicitly passing Publisher example. To generate a real-time facade, add Facades The namespace prefix can be:

 <? php namespace App; use Facades\App\Contracts\Publisher; use Illuminate\Database\Eloquent\Model; class Podcast extends Model { /** * Publish the podcast. * * @return void */ public function publish() { $this->update(['publishing' => now()]); Publisher::publish($this); } }

After using the real-time facade, the publishing service will be realized by using Facades The interface or class name after the prefix is resolved in the service container. When testing, we can use the facade test auxiliary function provided by Laravel to simulate this method call:

 <? php namespace Tests\Feature; use App\Podcast; use Tests\TestCase; use Facades\App\Contracts\Publisher; use Illuminate\Foundation\Testing\RefreshDatabase; class PodcastTest extends TestCase { use RefreshDatabase; /** * A test example. * * @return void */ public function test_podcast_can_be_published() { $podcast = factory(Podcast::class)->create(); Publisher::shouldReceive('publish')->once()->with($podcast); $podcast->publish(); } }

List of facade classes

Each facade and its corresponding underlying class are listed below, which is a very useful tool for going deep into the API document of a given root facade. Service container binding key Also included:
Facade class Service container binding
App Illuminate\Foundation\Application app
Artisan Illuminate\Contracts\Console\Kernel artisan
Auth Illuminate\Auth\AuthManager auth
Auth (Instance) Illuminate\Contracts\Auth\Guard auth.driver
Blade Illuminate\View\Compilers\BladeCompiler blade.compiler
Broadcast Illuminate\Contracts\Broadcasting\Factory
Broadcast (instance) Illuminate\Contracts\Broadcasting\Broadcaster
Bus Illuminate\Contracts\Bus\Dispatcher
Cache Illuminate\Cache\CacheManager cache
Cache (instance) Illuminate\Cache\Repository cache.store
Config Illuminate\Config\Repository config
Cookie Illuminate\Cookie\CookieJar cookie
Crypt Illuminate\Encryption\Encrypter encrypter
DB Illuminate\Database\DatabaseManager db
DB (instance) Illuminate\Database\Connection db.connection
Event Illuminate\Events\Dispatcher events
File Illuminate\Filesystem\Filesystem files
Gate Illuminate\Contracts\Auth\Access\Gate
Hash Illuminate\Contracts\Hashing\Hasher hash
Lang Illuminate\Translation\Translator translator
Log Illuminate\Log\Writer log
Mail Illuminate\Mail\Mailer mailer
Notification Illuminate\Notifications\ChannelManager
Password Illuminate\Auth\Passwords\PasswordBrokerManager auth.password
Password (instance) Illuminate\Auth\Passwords\PasswordBroker auth.password.broker
Queue Illuminate\Queue\QueueManager queue
Queue (instance) Illuminate\Contracts\Queue\Queue queue.connection
Queue (base class) Illuminate\Queue\Queue
Redirect Illuminate\Routing\Redirector redirect
Redis Illuminate\Redis\RedisManager redis
Redis (instance) Illuminate\Redis\Connections\Connection redis.connection
Request Illuminate\Http\Request request
Response Illuminate\Contracts\Routing\ResponseFactory
Response (instance) Illuminate\Http\Response
Route Illuminate\Routing\Router router
Schema Illuminate\Database\Schema\Builder
Session Illuminate\Session\SessionManager session
Session Illuminate\Session\Store session.store
Storage Illuminate\Filesystem\FilesystemManager filesystem
Storage (Instance) Illuminate\Contracts\Filesystem\Filesystem filesystem.disk
URL Illuminate\Routing\UrlGenerator url
Validator Illuminate\Validation\Factory validator
Validator (instance) Illuminate\Validation\Validator
View Illuminate\View\Factory view
View Illuminate\View\View

give the thumbs-up Cancel Like Collection Cancel Collection

<<Previous: Service Provider

>>Next: Contracts