laravel Facade理解

參考
https://sergeyzhuk.me/2016/05...php

Facade

Laravel facades serve as "static proxies" to underlying classes in the service container, providing the benefit of a terse, expressive syntax while maintaining more testability and flexibility than traditional static methods.

Laravel 門面爲 Laravel 服務的使用提供了便捷方式 ,再也不須要從服務容器中類型提示和契約解析便可直接經過靜態門面調用.laravel

能夠理解爲操做複雜對象的簡化方法,就是外觀模式裏的外觀類的方法.express

對應設計模式裏的外觀模式,對類實例的方法的封裝,使用起來更方便.設計模式

下面三種方法對某個實例方法來說沒有區別:app

//facade
SomeService::someMethod();
// and
app()->make('some.service')->someMethod();
// or
App::make('some.service')->someMethod();

核心是php的魔術方法__callStacic,全部調用Facade裏靜態方法,都會進入這個函數,進行真正的(代理)調用.函數

//Facde接口
    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);
    }
    public static function getFacadeRoot()
    {
        return static::resolveFacadeInstance(static::getFacadeAccessor());
    }
    protected static function resolveFacadeInstance($name)
    {
        if (is_object($name)) {
            return $name;
        }

        if (isset(static::$resolvedInstance[$name])) {
            return static::$resolvedInstance[$name];
        }

        //核心就在這,$app就是上面的ioc容器實例
        if (static::$app) {
            return static::$resolvedInstance[$name] = static::$app[$name];
        }

        //真正的實例來源
        public static function swap($instance)
        {
            static::$resolvedInstance[static::getFacadeAccessor()] = $instance;

            if (isset(static::$app)) {
                //註冊到Ioc容器
                static::$app->instance(static::getFacadeAccessor(), $instance);
            }
        }
    }

實現Facade接口的類,要實現getFacadeAccessorresolveFacadeInstance,關聯要真正的實例.測試

Date爲例子,其真正的實例是DateFactory.flex

class Date extends Facade
{
    const DEFAULT_FACADE = DateFactory::class;

    /**
     * Get the registered name of the component.
     *
     * @return string
     *
     * @throws \RuntimeException
     */
    protected static function getFacadeAccessor()
    {
        return 'date';
    }

    /**
     * Resolve the facade root instance from the container.
     *
     * @param  string  $name
     * @return mixed
     */
    protected static function resolveFacadeInstance($name)
    {
        if (! isset(static::$resolvedInstance[$name]) && ! isset(static::$app, static::$app[$name])) {
            $class = static::DEFAULT_FACADE;
            //swap執行真正的instance綁定到ioc容器
            static::swap(new $class);
        }

        return parent::resolveFacadeInstance($name);
    }
}

想用Date時,能夠:設計

//直接用門面靜態方法
 \Illuminate\Support\Facades\Date::createXXX()

但Laravel 的門面做爲服務容器中底層類的「靜態代理」,相比於傳統靜態方法,在維護時可以提供更加易於測試、更加靈活、簡明優雅的語法。代理

若是仍是嫌棄用以前use xxxx\Facades\xx太麻煩,config.app裏配置個alias:

?php
return [
    //...
    'aliases' => [
        'App'     => Illuminate\Support\Facades\App::class,
        'Artisan' => Illuminate\Support\Facades\Artisan::class,
        'Auth'    => Illuminate\Support\Facades\Auth::class,
        'Blade'   => Illuminate\Support\Facades\Blade::class,
        'Bus'     => Illuminate\Support\Facades\Bus::class,
        'Cache'   => Illuminate\Support\Facades\Cache::class,
        'Config'  => Illuminate\Support\Facades\Config::class,
    ],

    // ...
];

直接用就行了:

Cache::get(...);
相關文章
相關標籤/搜索