共计 2712 个字符,预计需要花费 7 分钟才能阅读完成。
一、container 容器类分析
Countable 巧用
Container 容器类文件是在 thinkphp\library\think 目录下的,我认为它是框架的一个精华,它可能很不便的治理框架的类,不便咱们应用。
在 Container 中,它用到了很多类,还有反射机制,所以反射机制是须要咱们去理解的一个货色。其中 Countable 是 php 内置的一个类,接下来咱们进行对它的演示。
首先在 extend 目录下创立一个 TestCountable 类,而后它继承 Countable,因为是继承的 Countable,须要把其中的 count 办法定义进去,不然会报错,而后在 count 外面轻易返回内容。接着在控制器 index.php 中创立办法去调用这个类,然而它的调用和其余的有点区别,惯例调用是这样的,$obj=new TestCountable(); $a = $obj->count();
而 Countable 是这样的$obj = new TestCountable(); $a = count($obj);
。这就是它的区别。
获取容器内的实例剖析
$this->instance
获取容器对象实例 $this->bind
容器绑定标识$this->name
容器标识别名
[APP] => think\App
[log] => think\Log
相似于容器绑定标识的内容 $this->instances
容器中的对象的实例
[think\App] => think\App Object
[think\Config] => think\Config Object 等等。
那么咱们如何去学习容器呢,咱们还是联合框架代码来进行剖析。
首先咱们定位到入口文件 index.php
这里它用了 Container 的 get 办法,并传入了一个 app 参数,咱们来看一下 get 办法的逻辑。
get 办法是获取容器中的对象实例。这里它传入了三个参数,三个参数各是什么意思,正文下面有,传入的 app 对应的就是 think\App,而后它用了单例模式,getInstance 就是一个单例,而后调用 make 办法。
首先会对 $vars 进行判断,如果是 true,就把它置空,让 $newInstace 为 true。接下来进行判断 $this->name[$abstract], 因为传入参数是 app,$abstract => app。而后判断 $abstract 有没有实例,默认是没有的,就返回一个实例。而后接着就是容器绑定标识,$concrete 对应的就是 think\App。接着如果它是闭包的话,就会走到 invokeFunction,如果不是,就设置容器标识别名,相当于 $this->name[“app”] = think\App。而后再去调用 make 办法,这个时候,传的参数就不一样了,第一个参数就成为 think\App,这个时候两个 isset 都是没有的,就不会走这两个逻辑。间接跳到 invokeClass 办法,这个时候会返回一个对象。而后把这个对象放入容器中的对象实例,最初返回这个对象。
invokeClass 办法
当初咱们讲一下 invokeClass 办法,这个办法传入了两个参数,第一是类名,第二是它的参数。而后实例化反射类 ReflectionClass,而后判断这个类外面是否有__make 办法,如果有的话就获取到这个类,接着判断这个类的属性是不是 public 或者 static,如果是的,就进行实例化,而后返回。而__make 办法在 Config 类里是存在的,所以这里实例化的是一个 Config 类。
容器类的应用场景
容器类能够这样应用,这种是应用的 Facade 门面的办法来应用的。
第二种能够这样应用,相似入口文件那样。这两种都能打印出 app 的 config 配置。
咱们还有另外一种应用场景的,这种场景咱们应用到了 php 的助手函数,在 helper.php 中的 app 办法中。
咱们能够这样用,间接app("config);
,这样能够间接拿到配置。
二、Facade 门面模式
门面为容器中的类提供了一个动态调用接口,相比于传统的静态方法调用,带来了更好的可测试性和扩展性。接下来还是通过代码来理解。
在 thinkphp\library\think 目录下有一个 Facade 文件,它相当于门面的一个父类,子类在 think\facade 目录下,外面有许多的类,它们都须要继承 Facade 父类。这些子类中都只有一个办法,getFacadeClass 办法,外面逻辑就是返回绑定的标识。它的作用是在 Facade 外面体现的。
这里获取到这个标识,而后判断有没有这个标识,如果有就返回这个实例,如果没有,就绑定到标识中去。
咱们接下来通过演示来剖析一下 Facade 代码。
咱们在 index 控制器外面创立一个 facade 办法,而后打印 Config::get("app");
,它是怎么走的呢,它会找到 think\facade\Config.php 这个文件,然而在这个文件外面是没有 get 办法的,而且在它的父类 Facade 外面也没有 get 办法,那么它是怎么执行的呢。因为 Facade 外面没有 get 办法,那么它会走到__callStatic 办法,而后去创立一个 get 办法。接下来咱们来具体解说一下__callStatic 办法。咱们创立一个 Test 类,在 Test 类外面增加__callStatic 办法,而后打印一下传入的参数,在应用层 index.php 去调用一下这个类,代码如下:
咱们调用的 abcd 办法在 Test 外面是不存在的,咱们看一下打印的参数是什么。
咱们持续看 Facade 类的__callStatic 办法,
在这里会执行 createFacade 办法,这个办法咱们在下面解释过了,所以最终会把 get 放入 $this->[name]
标识外面去。最终返回的是一个实例。
联合下面的形容,facade 办法就是依据容器外面是否有静态方法 get,如果有调用,如果没有就进行实例化,进行调用。
Facade 图例
Facade 实战
Facade 有两个应用场景,第一个:
咱们在 app 目录下创立 common 和 facade 文件夹,而后别离在两个目录下创立 Test 文件,common 下的 Test 外面创立 test 办法,并输入内容。facade 目录下须要继承 Facade 门面类,而后调用 getFacadeClass 办法,而后返回 common 下 Test 的门路,而后在应用层去调用 appfacadeTest::test();
第二种:
facade 目录下的 Test 文件不再写办法,而后在控制器外面这样应用。Facade::bind('app\facade\Test','app\common\Test'); app\facade\Test::test();