laravel 门面模式

最近在学习laravel框架的各种设计原理,今天看到门面模式这了,做下笔记:

Facade 工作原理

在 Laravel 应用中,门面就是一个为容器中对象提供访问方式的类。该机制原理由 Facade 类实现。Laravel 自带的门面,以及我们创建的自定义门面,都会继承自 IlluminateSupportFacadesFacade 基类。

门面类只需要实现一个方法:getFacadeAccessor。正是 getFacadeAccessor 方法定义了从容器中解析什么。然后 Facade 基类使用魔术方法 __callStatic() 代理门面上静态方法的调用,并将其交给通过 getFacadeAccessor 方法定义的从容器中解析出来的服务类来执行。

在config/app.php文件下有这样的配置:

'aliases' => [

        'App' => IlluminateSupportFacadesApp::class,
        'Artisan' => IlluminateSupportFacadesArtisan::class,
        'Auth' => IlluminateSupportFacadesAuth::class,
        'Blade' => IlluminateSupportFacadesBlade::class,
        'Broadcast' => IlluminateSupportFacadesBroadcast::class,
        'Bus' => IlluminateSupportFacadesBus::class,
        'Cache' => IlluminateSupportFacadesCache::class,
        'Config' => IlluminateSupportFacadesConfig::class,
        'Cookie' => IlluminateSupportFacadesCookie::class,
        'Crypt' => IlluminateSupportFacadesCrypt::class,
        'DB' => IlluminateSupportFacadesDB::class,
        'Eloquent' => IlluminateDatabaseEloquentModel::class,
        'Event' => IlluminateSupportFacadesEvent::class,
        'File' => IlluminateSupportFacadesFile::class,
        'Gate' => IlluminateSupportFacadesGate::class,
        'Hash' => IlluminateSupportFacadesHash::class,
        'Lang' => IlluminateSupportFacadesLang::class,
        'Log' => IlluminateSupportFacadesLog::class,
        'Mail' => IlluminateSupportFacadesMail::class,
        'Notification' => IlluminateSupportFacadesNotification::class,
        'Password' => IlluminateSupportFacadesPassword::class,
        'Queue' => IlluminateSupportFacadesQueue::class,
        'Redirect' => IlluminateSupportFacadesRedirect::class,
        'Redis' => IlluminateSupportFacadesRedis::class,
        'Request' => IlluminateSupportFacadesRequest::class,
        'Response' => IlluminateSupportFacadesResponse::class,
        'Route' => IlluminateSupportFacadesRoute::class,
        'Schema' => IlluminateSupportFacadesSchema::class,
        'Session' => IlluminateSupportFacadesSession::class,
        'Storage' => IlluminateSupportFacadesStorage::class,
        'URL' => IlluminateSupportFacadesURL::class,
        'Validator' => IlluminateSupportFacadesValidator::class,
        'View' => IlluminateSupportFacadesView::class,

    ],

举个栗子,lar的缓存调用是Cache::get()这样使用的,那么Cache显然是这里做了映射,那么对应的 IlluminateSupportFacadesCache 这个又是什么,追踪到这个类看看.

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

这个类只是继承了门面的基类  并定义了一个方法 返回一个cache名称,这里的cache其实是在app容器里能解析缓存类的对应名称.

那么Cache::get是一个怎么样的过程呢,其实在Facade类里是写了静态方法重载的,源码如下

 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];
    }

    return static::$resolvedInstance[$name] = static::$app[$name];
}

这里重载会去按cache的名称去容器里获取对象  最终还是去app容器里解析,然后获取对象后再调用get方法传入参数。

至于怎么把Cache对应到cache的门面上 就是用到了class_alias这个方法。

注:别名只是关联到门面类上  真正起作用的还是门面基类的重载。

原文地址:https://www.cnblogs.com/tudou1223/p/9361505.html