司机带你深入分析 Laravel 响应之视图一
前言
过4天就要回家了,好兴奋。好了不说废话,这一篇是Laravel响应的第二篇,如果你要阅读本篇,请先阅读老司机带你深入分析 Laravel 响应之一,这是十分有必要的,因为我会接着以前的代码讲。但是这里我要提醒大家一点,今天的这篇博文,我不会仔细的讲Blade引擎,这一部分因为内容较多,所以我放在在下周单独出来讲,今天的这篇就讲视图在整个Laravel的大体流程。
分析
我们进入到类Illuminate\Routing\Router
的toResponse
方法:
因为我们的视图类Illuminate\View\View
不符合上面的条件,所以代码会进入到我标出来的部分,所以这里生成了一个Illuminate\Http\Response
类的对象,我们这里假设它为$response
,根据老司机带你深入分析 Laravel 响应之一讲的,代码返回到public/index.php
文件中,所以接下来它的send
方法被调用,Illuminate\Http\Response
类本身并没有实现send
方法,但是它继承自Symfony\Component\HttpFoundation\Response
类,它的父类实现了这个方法,我们来看:
sendHeaders
方法的作用就是发送头部,这个我们在老司机带你深入分析 Laravel 响应之一讲过了,今天我们关心的是这个sendContent
方法,但是大家要注意了,我们的子类Illuminate\Http\Response
实现了sendContent
方法,我们来看:
因为我们的控制器返回的是一个视图,也就是这里的参数$content
,Illuminate\View\View
类实现了Illuminate\Contracts\Support\Renderable
接口,所以代码会进入到我标出来的代码中,所以接下来我们进入到Illuminate\View\View
类的render
方法中:
这里的参数$callback
为null,首先调用renderContents
在,这个是主角:
这个函数的代码中,只有getContents
的调用对我们的分析是重要的,这个方法如下:
很好,分析到这里,你是不是好奇这里的engine
属性是何时初始化的?没关系,老司机给你细细道来。
为了给大家讲解,我写了一个简单的控制器DebugController
,如下:
它的debug
方法调用了view
方法生成了一个视图,我们来看view
方法:
我们根据Illuminate\Contracts\View\Factory::class
搜索一下Laravel代码,注意搜索的时候不要忘记命名空间,不然你会不劳而获的,很快,在Illuminate\Foundation\Application
文件中(实际上这部分代码我们已经在之前的代码分析过了,不记得可以回过头去看),我们搜索到了结果:
Illuminate\Contracts\View\Factory::class
和view
相关联,我们再搜索view
,很快,我们在Illuminate\View\ViewServiceProvider
中,我们找到了答案:
哈哈,就是它,既然来到了这个文件,我们有必要再看一下这个类的其它方法registerViewFinder
和registerEngineResolver
,这2个方法分别向容器绑定了view.finder
和view.engine.resolver
,好了,我们registerFactory
所注册的单例方法中,首先,从全局的容器中,获取了view.finder
和view.engine.resolver
,view.engine.resolver
就是:
我们看一下注册的这个回调方法,首先生成了一个Illuminate\View\Engines\EngineResolver
类的对象,接下来的foreach循环,我们只关心blade值,这里会调用registerBladeEngine
方法:
上面的代码首先向容器中注册了一个名为blade.compiler
的单例,紧接着调用了Illuminate\View\Engines\EngineResolver
类的register
方法,这个方法也很简单:
这个地方后面会用到,这里只是先说下,好了,经过这些分析我们知道view.engine.resolver
就是Illuminate\View\Engines\EngineResolver
类的实例对象。
我们再来看'view.finder'
:
这个就很简单了,Illuminate\View\FileViewFinder
是一个视图文件寻找器,他会根据我们在config/view.php
文件中的配置寻找视图文件,比如我的配置:
关于Illuminate\View\FileViewFinder
不多说,很简单,大家有兴趣的自己去看哈。
经过爬山涉水,我们得到了view.finder
和view.engine.resolver
这2个大爷,我们回到Illuminate\View\ViewServiceProvider
的registerFactory
方法中,继续看,紧接着调用当前类的createFactory
方法:
这个方法也很简洁:
直接返回了一个\Illuminate\View\Factory
类的对象,好了,我们已经得到了想要的$factory
,返回到helpers.php
文件中:
我们看\Illuminate\View\Factory
类的make
方法:
他这里调用到了viewInstance
方法,这个方法如下:
我们看viewInstance
方法:
直接返回一个Illuminate\View\View
类的对象,但是我们来看看getEngineFromPath
方法,这个方法根据视图文件的扩展名确定当前所要使用的模板引擎:
因为我么你的视图文件是blade文件,文件扩展名是blade.php
,所以$engine
就是blade
,上面我们分析过了,所以这里的engines
属性就是Illuminate\View\Engines\EngineResolver
类的对象,我们看它的resolve
方法:
还记得,我们在上面调用了它的register
方法:
所以我们调用register
方法会得到Illuminate\View\Engines\CompilerEngine
类的对象,我们再一次回到\Illuminate\View\Factory类
的viewInstance
方法中,这里我们在Illuminate\View\View
类的构造函数中初始化了它的$engine
属性。
明白了这个之后,我们可以再次回到Illuminate\View\View
类的getContents
方法了:
这里我简要的和大家说下gatherData
方法,这个方法合并我们直接传递给视图的数据和我们的共享数据,共享数据是啥呢?还记不记得这个方法调用:
这个数据会在所有的模板中共享(看你的调用),gatherData
方法的作用就是如此。
不多说,进入到Illuminate\View\Engines\CompilerEngine
类的get
方法:
它的代码首先就是判断当前视图是否过期,如果过期的话,就重新编译视图文件,关于视图文件的编译,我们在下周再来仔细讲,这里我们看看$compiler
:
所以他就是Illuminate\View\Compilers\BladeCompiler
,关于Blade引擎,我们在下一篇博客中讲。
经过Blade引擎的编译,我们就得到了视图文件的内容,我们回到Illuminate\View\View
类的render
方法中,视图渲染的核心操作就算完成了,接下来的操作就和老司机带你深入分析 Laravel 响应之一中的一模一样了。
总结
作为Laravel视图系列的第一篇,希望大家仔细阅读,困难肯定是有的,但是读懂之后的喜悦也是无以言表的,加油。鄙人有个qq群,可以交流,也可以加我的微信,下方有,qq群如下:
本作品采用《CC 协议》,转载必须注明作者和本文链接
推荐文章: