一、安装thinkphp6
根据官方文档的说明:V6.0.3版本开始,必须通过Composer
方式安装和更新。需要先安装composer,再安装tp6,步骤照着官方文档来就行了(文档链接:https://www.kancloud.cn/manual/thinkphp6_0/1037481)。(注:运行php think run时,需要在tp的跟目录下)
二、运行流程
跟目录下的think文件---->自动加载类(PSR-4标准)---->容器管理类---->http类---->response类
整条路由访问链:App类--->Http类--->Middleware类--->Pipeline类---->TraceDebug类---->Request类----->Route类--->Rule类--->RuleName类---->think\route\dispatch\Url类及其两个父类------>Response类
1.自动加载类流程
vendor/autoload.php----->vendor/composer/autoload_real.php---->vendor/composer/autoload_static.php------>vendor//composer/ClassLoader.php
spl_autoload_register的使用:相当于将Test类名作为参数传给函数my_autoloader,找到Test类的路径并include加载
function my_autoloader($class) {
include 'classes/' . $class . '.class.php';
}
spl_autoload_register('my_autoloader');
$test = new Test();
vendor//composer/ClassLoader.php:自动加载类(spl_autoload_register),一些set/get方法,根据使用的类名找到对应类的路径,并include进行加载
vendor/composer/autoload_static.php:命名空间路径数据类(传入参数ClassLoader类,并将成员变量值赋值给ClassLoader类的成员变量)
vendor/composer/autoload_real.php:进行注册,并生成自动加载类(注册一个自动加载类,将此类传值给命名空间路径类,自动加载类调用方法进行自动加载)
2.容器管理类(子类:App 和父类: Container)
Container类:围绕着变量instances和bind进行的一些操作(增加绑定、删除绑定、判断绑定是否存在等)和创建类实例的相关操作
成员变量:
instances:容器池,键值对保存各种类的实例
bind:别名,键值对保存各种别名对应类名
成员方法:
各种魔术方法;
getInstance:获取实例(单例模式)
setInstance:设置实例
make:创建类的实例(通过别名查找instances,存在则返回;不存在则进行查找bind,存在则生成实例并绑定,不存在则提示报错)ReflectionFunction类和ReflectionMethod类和ReflectionClass类的使用
factory:创建工厂对应实例(可以用来在入口处创建类的实例,如:echo $app->factory('index','app\\controller\\')->hello();)
App类:
成员变量:
各种目录路径变量;
initializers:保存需要初始化的应用类名(error类等)
services:保存注册的系统服务
initialized:是否初始化(默认false)
成员方法:
构造函数:初始化路径变量,设置并绑定实例类
一些关于服务类的方法;
一些set/get方法;
initialize:初始化应用
(1)加载环境变量($_ENV,Env类);
(2).判断并进行调试模式;
(3).调用方法load()加载应用和配置信息;
(4).语言包设置;
(5).初始化变量initializers保存的类名实例化;
load:加载一些公共函数文件、配置信息文件(config/)、注册应用事件(Event类:观察者模式)、注册服务(Service类)
3.Http类
一些应用目录变量和相关目录的方法;
run:执行应用程序-----------(步骤一)
(1)创建Request类(接受并处理请求信息类);
(2)调用runWithRequest方法,并最终返回Response类(发送服务器响应信息类);
runWithRequest:执行应用程序------------(步骤二)
(1)接受参数Request类(run方法创建的Request类);
(2)加载全局中间件(调用loadMiddleware方法);
(3)运用中间件类中管道模式(pipeline方法)处理Request类,并返回Response类;
dispatchToRoute:对路由的处理方法---------进入路由功能模块--------(步骤七)
(1)调用loadRoutes方法加载路由配置;
(2)调用Route类dispatch方法进行路由调度
loadMiddleware:调用了Middleware类的import方法,导入中间件;
loadRoutes:加载路由配置文件
reportException和renderException:异常处理方法
end:执行结束,保存日志等
4.Middleware类
成员变量:queue:数组:保存注册的中间件(键值key作为中间件的类型,值中包含有中间件类名、方法名和参数信息,目前公共类型的中间件中有TraceDebug类)
import:导入中间件,对参数调用了add方法;
add:注册中间件,将参数进行处理(buildMiddleware方法)后,保存至queue变量中;
buildMiddleware:解析中间件
(1)判断参数的类型,如果是Closure类,直接组装(中间件用的是构造函数);如果是字符串,需查看配置是否存在别名,再进行组装(此时用默认方法名handle,也就是这样的中间件必须实现handle方法)
(2)最终组装成包含中间件类名、方法名和参数的二维数组(类名和方法名一起组成数组,参数一个数组)
route和controller:注册路由和控制器中间件(调用add方法);
unshift:将中间件注册到开始位置
all:根据传入的中间件类型参数,获取对应的所有中间件;
pipeline:调度管道,根据中间件类型参数,对对应的中间件进行调度----------(步骤三)
(1)获取类型下的所有中间件并进行排序(sortMiddleware方法);
(2)对排序后的中间件数组进行处理(因为保存有类名、方法名和参数,则可以实例化中间件类,并传入参数调用类的方法,方法的返回值必须为Response类),(array_map和call_user_func),得到保存Response类的数组;
(3)将得到的这个数组传入Pipeline类(属性:pipes)中,并最终返回Pipeline类实例;
end:结束调度,循环执行所有中间件类中的end方法(如果有此方法),将Response类作为参数;
handleException:异常处理方法
sortMiddleware:中间件排序,读取配置中的排列顺序(类名在配置数组中的顺序),uasort对中间件数组进行排序;
getMiddlewarePriority:获取中间件优先级,根据类名获取在排序数组(进行了倒序)中的位置(不存在则为-1),并返回位置;
5.Pipeline类
成员变量:
passable:
pipes:
exceptionHandler:接收异常处理器
成员方法:
send:设置变量passable;初始数据(如:在Http类接收了Request类参数)------(步骤五)
through:设置变量pipes;调用栈(如:在Middleware类接收了对中间件处理后生成的Response类数组)------(步骤四)
then:执行-----(如:接收Http类中的dispatchToRoute方法的Response类返回值,)------(步骤六)
组装array_reduce函数的三个参数
(1)第一个参数:pipes数组进行倒序后的数组(如:Response类数组)
(2)第二个参数:调用carry方法生成的处理函数:对pipes数组中的每个元素进行执行操作(如:合并Response类数组属性)
(3)第三个参数:调用传递过来的Closure类参数进行执行的结果作为初始值(如:传进来的Response类参数)
(4)用array_reduce函数的返回结果(如:合并后的Response类)进行执行操作,以passable变量(如:初始数据时接收的Request类)作为参数
(如:最终将Response类数组的所有属性进行合并形成新的Response类)
(5)最终返回结果(如:最终返回以Request类作为参数的新的Response类)
carry:对pipes数组中的每个元素进行执行操作
whenException:设置exceptionHandler变量异常处理器(如:将Middleware类的异常处理方法作为参数设置)-(跟步骤四一起)
handleException:对设置的异常进行处理(如:执行Middleware类的异常方法)
后面还有关于:a.路由的流程,b.异常类,c.模板类,d.数据库类,e.缓存类,f.日志类,g.事件类、服务类和中间件的使用等