thinkphp6 Facade模式

发布于 2019-12-06 22:47:15

说明

上一篇的例子中,User控制器引入了命名空间think\facade\Event,接着这样调用think\facade\Event::subscribe(),可打开think\facade\Event类的文件一看:

class Event extends Facade
{
    /**
     * 获取当前Facade对应类名(或者已经绑定的容器对象标识)
     * @access protected
     * @return string
     */
    protected static function getFacadeClass()
    {
        return 'event';
    }
}

该类中只定义了一个getFacadeClass方法,是不存在subscribe方法的。程序实际调用的是think\Event类的subscribe方法,而且该方法也不是静态方法,在这里却是静态调用。这是如何做到的呢?

Facade的原理

Facade模式,中文一般翻译为「门面」模式,是指为一堆零散的风格不一的子系统设计一个统一的调用接口,这个接口就像是一个「门面」。Facade模式在这里的用处是把动态类方法转换为可静态调用的方法。接着,我们看看具体的实现过程。

think\facade\Event类继承了think\Facade类。查看think\Facade类,注意到其定义了一个魔术方法:

public static function __callStatic($method, $params)
{
    return call_user_func_array([static::createFacade(), $method], $params);
}

在PHP中,当一个类静态调用一个不存在的方法,将会触发该魔术方法,所以think\facade\Event::subscribe()这样调用的时候,首先是执行该__callStatic方法。
在这个例子中,该方法$method参数传入的值是subscribe$params传入的值是app\subscribe\User
先看看这其中的static::createFacade()方法:

protected static function createFacade(string $class = '', array $args = [], bool $newInstance = false)
{
    // 如果$class为空,那么$class就等于当前的类(think\facade\Event)
    $class = $class ?: static::class;
    // 解析出该Facade类实际要代理的类
    $facadeClass = static::getFacadeClass();

    if ($facadeClass) {
        $class = $facadeClass;
    }
    // 是否要一直新建实例(否则就是单例模式)
    if (static::$alwaysNewInstance) {
        $newInstance = true;
    }
    // 使用PHP的反射类实例化该类(比如,实例化think\Event)
    return Container::getInstance()->make($class, $args, $newInstance);
}

具体分析见注释。最后一个$newInstance参数可以设置是否使用单例模式。该方法最后返回一个类的对象(Facade类所代理的类),在本例子中是think\Event类的对象。

最后,程序执行call_user_func_array([static::createFacade(), $method], $params),在这个例子中,就等于执行:$obj->subscribe('app\subscribe\User')(其中,$objthink\Event类的一个对象)。

Bug天天改,头发日日疏,码字不易,如果有帮助到你,就点击"下方感谢"支持一下把.

©声明:本站所有文章,如无特殊说明或标注,均为izhnagbo.cn原创发布。任何个人或组织,在未征得本站同意时,禁止复制、盗用、采集、发布本站内容到任何网站、书籍等各类媒体平台。如若本站内容侵犯了原著者的合法权益,可联系我们进行处理。本文链接 https://izhangbo.cn/article/24.html
0 条评论

学习
记录

发布
问题