当前位置: 首页 > 后端技术 > PHP

Tp5源码分析第四步--------容器类和门面类

时间:2023-03-30 02:38:24 PHP

1.容器类分析它是框架的精髓,可以很方便的管理框架的类,方便我们使用。在Container中,它使用了很多类和反射机制,所以反射机制是我们需要了解的。其中,Countable是php的内置类,接下来我们将对其进行演示。首先在extend目录下创建一个TestCountable类,然后它继承Countable。因为是继承的Countable,所以需要定义count方法,否则会报错,然后在count中返回内容。然后在controllerindex.php中创建一个方法来调用这个类,但是它的调用和其他的有点不一样。常规调用是这样的,$obj=newTestCountable();$a=$obj->count();而Countable是这样的$obj=newTestCountable();$a=count($obj);.这就是不同之处。获取容器中的实例分析$this->instance获取容器对象实例$this->bind容器绑定标识$this->name容器标识别名[APP]=>think\App[log]=>think\Log类似to容器绑定所标识的内容$this->instances容器中对象的实例[think\App]=>think\AppObject[think\Config]=>think\ConfigObject等等。那么我们如何学习容器呢?我们还是结合框架代码来分析一下。首先我们找到入口文件index.php,它使用了Container的get方法,传入了一个app参数。我们来看看get方法的逻辑。get方法是获取容器中的对象实例。这里传入了三个参数,三个参数分别是什么意思,上面的注释,传入的app对应think\App,然后使用的是单例模式,getInstance是单例,然后调用make方法.首先会判断$vars,为真则为空,$newInstace为真。接下来判断$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。如果是,则实例化它,然后返回。Config类中存在__make方法,所以这里实例化了一个Config类。容器类的使用场景容器类可以这样使用,就是Facade的方法使用。第二种可以这样用,类似于入口文件。这两个都可以打印出app的config配置。我们还有另一个使用场景。在这种情况下,我们在helper.php中的app方法中使用php辅助函数。我们可以这样使用,直接app("config);,这样我们就可以直接获取配置。其次,Facade门面模式为容器中的类提供了静态调用接口。相对于传统的静态方法调用,带来了更好的可测试性和扩展性,接下来就是通过代码来理解了,在thinkphp\library\think目录下有一个Facade文件,相当于facade的一个父类,子类在think\facade目录,里面有很多类,都需要继承Facade父类。这些子类中只有一个方法,就是getFacadeClass方法,里面的逻辑就是返回绑定ID。它的作用体现在Facade中。这里获取logo,然后判断是否有这个logo,如果有则返回这个实例,如果没有则绑定到logo上。下面我们通过一个演示来分析Facade代码。我们在indexcontroller中创建一个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]标识符中。最后返回的是一个实例。结合上面的描述,门面方法是根据容器中是否有静态方法get,如果有调用,如果没有则实例化调用。Facade图例Facade实战Facade有两种使用场景,第一种:我们在app目录下创建common和facade文件夹,然后分别在两个目录下创建Test文件,在common下的Test中创建一个测试方法,并输出内容.在facade目录下,需要继承Facade门面类,然后调用getFacadeClass方法,然后返回common下Test的路径,然后在应用层调用appfacadeTest::test();第二种方法:facade目录下的Test文件不再写方法,然后在controller中这样使用。Facade::bind('app\facade\Test','app\common\Test');应用\外观\测试::测试();