三、优化在框架中facade的使用
在上文中我们从实例化类到使用门面方式实现了同一个功能。
虽说想要实现的效果显示出来了,但是代码还是不够简洁优美的,结构也比较混乱。
接下来咔咔会给大家提供一个可行的方案,如果你有其它的方案可以提出来哈!评论区见。
在正常开发工作中自定义的门面类不可能只有一个或者几个,在复杂的项目中门面类会有很多。
既然多,那就需要进行管理。
首先建立一个属于门面的配置类。
并将代理类和实际类对应起来,然后设置别名。
此时需要建立一个钩子文件,将门面类注册和门面类别名注册都放在里边进行执行。
还有最后一步,那就是钩子文件虽然创建了但是没有执行。
那么钩子文件应该什么时候执行呢!那就是在应用初始化的时候进行加载。
在TP5.1中应用初始化的配置是在application/tags.php这个文件中。
在应用初始化的配置项里把钩子文件配置进去即可。
测试
最后一步就是测试了,依然是执行application/index/controller/Facade.php文件中的getUserInfo方法。
根据测试结果可以得知我们的方案代码编写没有问题。
这里有没有发现一个问题,就是既然在钩子中定义了门面类的别名了,但是在这里并没有使用。
接下来我们使用别名来测试一下。
四、门面类源码解析
在解析源码之前先认识俩个方法。
__callStatic:当访问不存在的静态方法时,会调用此方法。
call_user_func_array:可以直接用此函数来直接调用函数。
我们就从获取配置文件开始解析
执行Config::get('facade.');会执行到文件thinkphp/library/think/facade/Config.php中。
在这个文件中就是之前说的,如果存在getFacadeClass方法就会直接返回对应的别名。
如果不存在的话就需要使用bind方法来进行门面绑定。
这里如果不明白就需要去文档好好看看门面那一章节哈!
在上边类中是不存在get方法的,所以就会直接调用thinkphp/library/think/Facade.php文件中的__callStatic方法。
这个方法就是文章开头就直接说明的,访问不存在的静态的方法时则会调用此方法。
接着就会执行本类中的createFacade这个方法
在这个方法里边有一行代码是这个样子的$facadeClass = static::getFacadeClass();这段代码会在下文做详细的说明。
因为在子类中也有同样的方法,在本类中也有同样的方法但是在本类中的方法是没有任何返回值的。
这时你有没有一丝丝的困惑,这里使用的static到底会执行哪里的方法。或者这样想,为什么会执行子类的方法。
保留这些疑问将会在下文给你细细的讲来,先来把门面类的源码看完。
在这个方法中主要看我圈起来的几个地方。
第一处就是从子类的getFacadeClass方法获取类的别名。
第二处是当子类没有getFacadeClass方法时,从手动绑定的属性中获取。
第三处就是之前文章提到的容器了,这里就不对这里做详细说明了,如果不会的点开主页去看之前的文章。
五、static关键字
在这里不得不说明一下static这个关键字。
新学习的伙伴估计只能知道static是用来定义静态变量和静态方法的。
当然这里不会去给大家说怎么定义静态方法和静态变量,而是说一个非常非常小的细节点。
先看一个实例,这个实例也是在阅读门面源码时,咔咔根据门面源码改编过来的。
咔咔这里新建了俩个文件,分别为test和test1。
test继承test1文件,并且都有同样的方法getKaka。
test的源码
test1源码
控制器进行调用
打印结果
这个时候有没有一点点疑惑,这里怎么打印出来的是147,而不是456呢!
修改test1的代码,把static改为self
打印结果
使用self的代码相信大家都看的明白,那为什么使用static就出现了有可能不太明白的结果呢!
此时就是文档开始起作用了,但是当你打开PHP文档会发现,在static这一篇中并没有对这类情况作出说明。
经过咔咔多次测试和查阅资料,最终总结结果如下。
static::$test 如果有被继承的话 默认调用子类 ,否则调用的是自身
self::$test 如果有被继承的话,默认调用本类
放在本实例中来说明就是,当test继承test1时。
在test1中使用static调用方法getKaka时,默认调用的是test类中的getKaka,也就是子类的方法。
在test1中使用self调用方法getKaka时,默认调用的是test1类中的getKaka,也就是本类的方法。
这个小小的细节也是咔咔无意中发现的,如果有什么不对的地方可以提出来,咔咔作出修改。
因为在继承这方面还有另外一种情况,咔咔私下会进行测试,在这里就不说明了。
这里对这个static做出解释主要是为了解释thinkphp/library/think/Facade.php文件中这个行代码。
因为这行代码调用的方法在子类和父类都存在,所以咔咔为了不让大家出现迷惑就写出来做一个简单的介绍。