This is the 13th day of my participation in the August More Text Challenge.More challenges in August

Before, I wrote an article about Laravel improving the efficiency of DB query. After forwarding it to the group, some people questioned me and said, “Laravel is the framework he used several years ago, I didn’t expect that there are still people using it now.”

Nani, what do you mean? Don’t forget PHP is the best language!

Personally, Laravel is a very elegant development framework: elegant design patterns, powerful feature implementations, easy extensions, constant release updates, and most importantly, the best technology development community to date, in my opinion.

I have to make a Call for Laravel.

Laravel released version 8.0 on September 8, 2020. Laravel is scheduled to release version 9.0 on January 25, 2022.

Here I would like to introduce the new features of the latest Laravel release (8.0) :

Laravel 8 with the introduction of Laravel Jetstream, model factory classes, Migration compression, queue batching, improved rate limiting, queue improvements, dynamic Blade components, Tailwind paging view, Time test Assistant, artisan Serve improvements, Improvements to the event listener, along with various other bug fixes and usability improvements, continue to improve Laravel 7.x.

introduce

Facades provide a “static” interface to the application’s service container. Laravel comes with a lot of Facades and has access to most of the features.

Laravel Facades are essentially “static proxies” for the underlying classes in the service container, providing more flexibility, easier to test, and more elegant syntax when used than traditional static methods.

All Laravel Facades are defined under the Illuminate\Support\Facades namespace. So, we can easily use a Facade:

use Illuminate\Support\Facades\Cache;

Route::get('/cache', function () {
    return Cache::get('key');
});
Copy the code

In the Laravel documentation, there is a lot of sample code that uses Facades to demonstrate the various capabilities of the framework.

When to use Facades

Facades have many advantages. It provides a simple, easy-to-remember syntax that eliminates the need to manually inject or configure long class names. In addition, their unique invocation of PHP static methods makes testing very easy.

However, there are some areas where you need to be careful when using Facades. The main danger when using Facades is that it causes the scope of a class to swell. Because Facades are so simple to use and require no injection, we inadvertently use many Facades in a single class, resulting in larger and larger classes.

With dependency injection, however, the more classes you use, the longer the constructor becomes, visually noting that the class is a bit too big. So when using Facades, pay special attention to controlling the size of the class and keeping the scope of the class short.

Tip: When developing third-party extensions that interact with Laravel, it’s best to inject Laravel contracts instead of Facades. Because the extension pack is built outside of Laravel, you cannot test helper functions using Laravel Facades.

Facades versus dependency injection

One of the main benefits of dependency injection is the ability to swap implementations of injected classes. This is useful for testing because you can inject a mock or stub and assert various methods on the stub.

In general, a truly static method cannot mock or stub. But Facades use dynamic methods to proxy calls to object methods that are resolved in the service container, and we can test Facades as well as injecting class instances.

For example, routes like the following:

use Illuminate\Support\Facades\Cache;

Route::get('/cache', function () {
    return Cache::get('key');
});
Copy the code

We can verify the Cache::get method by writing the following test code with the desired parameters:

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

Facades versus helper functions

In addition to Facades, Laravel includes various “helper functions” to implement common functions such as generating views, triggering events, scheduling tasks, or sending HTTP responses.

Many helper functions have Facades for them.

For example, the following Facades serve the same purpose as the helper function:

return View::make('profile'); return view('profile'); CopyCopy the code

There is no real difference between a Facade and a helper function. When you use helper functions, you can test them as if they were facades.

For example, the following route:

Route::get('/cache', function () {
    return cache('key');
});
Copy the code

In the underlying implementation, the secondary function cache actually calls the GET method of the cache Facade.

So, even though we are using an auxiliary function, we can still verify the method by writing the following test code with the desired parameters:

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

How Facades work

In a Laravel application, a Facade is a class that can access objects from a container. The core component is the Facade class.

Both Laravel’s built-in and custom Facades inherit from the Illuminate\Support\Facades\Facade class.

The Facade base class uses the __callStatic() magic method, which is not called until the object has been resolved from the container. In the following example, Laravel’s caching system is called.

Looking through this code, we can assume that the static method get is called in the Cache class:

<? php namespace App\Http\Controllers; use App\Http\Controllers\Controller; use Illuminate\Support\Facades\Cache; Class UserController extends Controller {/** * Displays information about a given user. * * @param int $id * @return Response */ public function showProfile($id) { $user = Cache::get('user:'.$id); return view('profile', ['user' => $user]); }}Copy the code

Notice that in the code above, we “imported” the Cache Facade. This Facade acts as a proxy to access 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 the Laravel cache service.

If we look at the Illuminate Support Facades Cache class, you’ll see that the static method get is not present at all:

Class Cache extends Facade {/** * Gets the registered name of the component. * * @return string */ protected static function getFacadeAccessor() { return 'cache'; }}Copy the code

The Cache Facade inherits the Facade class and defines the getFacadeAccessor() method.

This method returns the name of the service container binding. When a user invokes any static method on the Cache Facade, Laravel parses the Cache binding from the service container and the requested method (in this case, the GET method) for the object to run.

Real-time Facades

With real-time Facades, you can treat any class in your application as a Facade. To illustrate how this is used, let’s look at another approach.

For example, suppose our Podcast model has a publish method.

However, to publish the Podcast, we need to inject an instance of Publisher:

<? php namespace App\Models; use App\Contracts\Publisher; use Illuminate\Database\Eloquent\Model; Class Podcast extends Model {/** * Publishes podcasts. * * @param Publisher $publisher * @return void */ public function publish(Publisher $publisher) { $this->update(['publishing' => now()]); $publisher->publish($this); }}Copy the code

By injecting the publisher’s implementation into the method, we can easily test this method because we can emulate the injected publisher. However, it requires us to pass in a publisher instance every time we call the Publish method.

With real-time Facades, we can maintain the same testability without having to explicitly go through Publisher instances.

To generate a real-time Facade, add Facades to the namespace of the imported class:

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

When a real-time Facade is used, the publisher implementation solves the problem of the service container by using parts of the interface or class name that appear after the Facades prefix.

During testing, we can simulate this method call using Laravel’s built-in facade test helper function:

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

Gorgeous dividing line

For more on Laravel, check out my column: Server Development from Beginner to Master

Recommended reading

  1. I’m still working on Laravel? Don’t forget PHP is the best language. (1) How does Laravel elegantly set global variables

  2. I’m still working on Laravel? Don’t forget PHP is the best language. (2) Laravel Jetstream and model Factory classes

  3. I’m still working on Laravel? Don’t forget PHP is the best language. (3) Migration compression, queue batch processing, improve rate limit

  4. I’m still working on Laravel? Don’t forget PHP is the best language. (4) Optimization of maintenance mode

  5. I’m still working on Laravel? Don’t forget PHP is the best language. (5) Dynamic Blade event listener optimizes event test assistant

  6. I’m still working on Laravel? Don’t forget PHP is the best language. (6)

  7. I’m still working on Laravel? Don’t forget PHP is the best language. (7) Laravel Installation Guide

  8. I’m still working on Laravel? Don’t forget PHP is the best language. (8) Directory structure

  9. I’m still working on Laravel? Don’t forget PHP is the best language. (9) Deployment of Laravel

  10. I’m still working on Laravel? Don’t forget PHP is the best language. (10) Introduction of Laravel’s request cycle

  11. I’m still working on Laravel? Don’t forget PHP is the best language. (11) Laravel service container

  12. I’m still working on Laravel? Don’t forget PHP is the best language. (12) Service providers

Last but not least

Technical group please come here. Or add my wechat account wangzhongyang0601 to learn together.