laravel 源码解读


注册’app’,’Illuminate\Container\Container’到容器 2> 注册基础服务提供者。事件和路由服务 3> 配置核心类的别名 b) 注册http核心类,console核心类,异常处理类到容器 4,从容器获取http核心类实例$kernel。 5,调用$kernel->handle(Request)处理请求 a) 调用bootstrap方法,依次执行bootstrappers数组定义的组件,这里是以下组件: ‘Illuminate\Foundation\Bootstrap\DetectEnvironment’==>加载项目配置文件.env ‘Illuminate\Foundation\Bootstrap\LoadConfiguration’==>加载config目录下的配置文件,用文件名为key,文件内容数组为value,设置到$app[config]中.设置时区和内部字符编码 ‘Illuminate\Foundation\Bootstrap\ConfigureLogging’==>注册log日志实例 ‘Illuminate\Foundation\Bootstrap\HandleExceptions’==>设置错误异常处理,shutdown_function等 ‘Illuminate\Foundation\Bootstrap\RegisterFacades’==> Facade初始设置,别名类加载类初始 ‘Illuminate\Foundation\Bootstrap\RegisterProviders’==> 加载$app[config][‘app.providers’]中的provider.注册需要立即注册的provider ‘Illuminate\Foundation\Bootstrap\BootProviders’==>调用所有注册的provider的boot方法。 b) 利用pipeline方式执行请求,这里会以方法的stack组依次调用Middleware中间件,并处理请求 c) 促发kernel.handled事件,返回response 6. 发送 response 头和内容 7,调用$kernel的中间件的terminate方法。调用$app中注册的terminatingCallbacks方法,方法参数也会用IOC注入 从容器中根据名称获取实例的过程,即$app->make($abstract, array $parameters = []) 1.获取名称对应的别名,检测是否已经有这个名称对应的实例了,有则直接返回 2.根据名称获取注册时对应的闭包,类名或别名等。 3.如果是类名且与$abstract不同,需要递归调用make方法来获取实例 4.如果是闭包或者类名与$abstract相同,调用build方法 a) 如果是闭包,调用闭包函数获取实例 b) 如果是类名,利用反射机制获取实例,这里会获取被实例化类的构造参数,根据参数的类全名,调用make方法获取实例,来自动传入到构造参数里,即IOC机制。 5.如果绑定是共享(单例)的,则把这个实例添加到容器的实例缓存中 6.返回实例 pipeline方式执行请求解释 1.代码解释 (new Pipeline($this->app)) //设置容器 ->send($request)//设置要传递的参数,这里是request ->through($this->app->shouldSkipMiddleware() ? [] : $this->middleware)//要使用的中间件 ->then($this->dispatchToRouter()); // 执行方法,会先经过中间件,在调用dispatchToRouter来处理请求 2.then方法解释 a)代码解释 public function then(Closure $destination) { $firstSlice = $this->getInitialSlice($destination);//最终请求处理方法 $pipes = array_reverse($this->pipes);//倒序pipes,这里就是中间件 return call_user_func( array_reduce($pipes, $this->getSlice(), $firstSlice), $this->passable //passable就是request, ); } b) array_reduce($pipes, $this->getSlice(), $firstSlice),解释 protected function getSlice() { return function ($stack, $pipe) {return function ($passable) use ($stack, $pipe) {…..}}; } array_reduce内部执行情况: 第一次,function ($stack, $pipe) 中的$stack是$firstSlice,$pipe是$pipes[0],返回方法function ($passable) use ($stack, $pipe),这个方法会被最后一个中间件调用,即中间件handle的$next 第二次,function ($stack, $pipe) 中的$stack是上面返回的方法,$pipe是$pipes[1],返回方法function ($passable) use ($stack, $pipe),这个方法会被最后第二个中间件调用,即中间件handle的$next 下同…… 这样返回方法被按类似栈方式压入,执行最后被返回的方法时,会依次出栈调用 请求处理router->dispatch($request)解释 1. 促发router.before事件 2. 找到匹配的route 3. 促发router.matched事件 4. callRouteFilter 5. 获取匹配route的中间件 6. Pipeline方式执行中间件和通过$route->run(Request $request)调用action 方法,来返回$response。action方法的参数会使用IOC方式,根据参数的类名注入容器中的实例 7 callRouteAfter 8 促发router.after事件 视图模板解析过程: 1. 在action中实例化一个View,View::make($viewName,array $params)。在模板目录中查找以$viewName开头的,模板解析引擎的特定扩展名结尾[.php,.blade.php]的文件,即获取对应的模板文件和解析引擎。 2. 利用$route->prepareResponse($request, $response)对$response 即上面的$view实例进行解析 a)调用$view->render方法。 aa)调用模板引擎的get(path,data),path是模板文件的路径,data是业务数据和模板共享数据的集 01> 模板对应的解析结果是否过期,未过期不用再解析。用模板文件和结果文件的修改时间进行对比来判断。 02> 编译模板文件,生成php模板缓存文件。 03> 执行缓存文件 04> 返回内容。 ]]>