Laravel核心 - 门面Facades


Laravel的门面Facades是什么

门面为应用服务容器的绑定类提供了一个静态接口。Laravel内置了很多门面,你可能在不知道的情况下正在使用它们。laravel的门面作为服务容器中低层类的静态代理,相比于传统静态方法,在维护时能够提供易于测试、更加灵活、简明优雅的语法。

何时使用门面Facades

门面有许多优点,其提供了简单易记的语法,让我妈无需记住长长的类名即可使用laravel提供的功能特性,此外,由于他们对php动态方法的独到用法,使得他们很容易测试。

但是使用门面也有需要注意的地方,一个最主要的危险就是类范围蠕变。由于门面如此好用并且不需要注入,在单个类中使用过多门面,会让类很容易变得越来越大。使用依赖注入则会让此类问题缓解,因为一个巨大的构造函数会让我们很容易判断类在变大。因此,使用门面的时候尤其注意类的大小,一遍控制其有限职责

门面的工作原理

门面工作原理分为两步,

  1. 第一步是编写门面类

    class Cache extends Facade
    {
     /**
      * 获取组件注册名称
      *
      * @return string
      */
     protected static function getFacadeAccessor() { 
         return 'cache'; 
     }
    }

    他会通过服务容器绑定的接口名获取对应类的实例

  2. 他会调用魔术方法__callStatic,通过这个魔术方法实现调用静态方法去调用实例的动态方法

     /**
      * Handle dynamic, static calls to the object.
      *
      * @param  string  $method
      * @param  array   $args
      * @return mixed
      *
      * @throws \RuntimeException
      */
     public static function __callStatic($method, $args)
     {
         //通过第一步获取到的服务容器实例
         $instance = static::getFacadeRoot();
    
         if (! $instance) {
             throw new RuntimeException('A facade root has not been set.');
         }
    
         //调用实例的动态方法
         return $instance->$method(...$args);
     }

总的来说:在laravel应用阿忠,门面就是一个为容器中对象提供访问方式的类。该机制原理由Facade类实现。laravel自带的门面,以及我们创建的自定义门面,都会继承自Illuminate\Support\Facades\Facade 基类.

门面类只需要实现一个方法:getFacadeAccessor。正是这个方法定义了从容器中解析什么,然后Facade基类使用魔术方法__callStatic从你的门面调用解析对象.

实时门面(不需要自己编写相对应的门面类,有laravel自己去动态解析获取对应的类

个人理解:相当于省去了第一个步骤,我们创建门面类告诉laravel应用应该从服务容器解析什么,直接通过命名空间自动的解析对应类的实例

<?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();
    }
}

上面例子,我们通过命名空间use Facades\App\Contracts\Publisher;告诉应用我们要使用实时的门面类,通过字符串处理,将App\Contracts\Publisher通过服务容器解析,然后交由门面.


文章作者: 我若为侠
版权声明: 本博客所有文章除特別声明外,均采用 CC BY 4.0 许可协议。转载请注明来源 我若为侠 !
 上一篇
Docker学习笔记(一)-什么是Docker? Docker学习笔记(一)-什么是Docker?
docker简介docker是什么? Docker 是一个开源的应用容器引擎,基于 Go 语言 并遵从Apache2.0协议开源。 Docker 可以让开发者打包他们的应用以及依赖包到一个轻量级、可移植的容器中,然后发布到任何流行的 Li
下一篇 
Laravel核心 - 服务容器 Laravel核心 - 服务容器
Laravel的服务容器是什么laravel的服务容器是用于管理类的依赖和执行依赖注入的工具。依赖注入实质上是指:类的依赖项通过构造函数或者某些情况下通过setter方法注入到类中 setter就是类似魔术方法__set的方法,也可以自定
2020-07-11
  目录