司机带你深入分析 Laravel 响应之视图一

前言

过4天就要回家了,好兴奋。好了不说废话,这一篇是Laravel响应的第二篇,如果你要阅读本篇,请先阅读老司机带你深入分析 Laravel 响应之一,这是十分有必要的,因为我会接着以前的代码讲。但是这里我要提醒大家一点,今天的这篇博文,我不会仔细的讲Blade引擎,这一部分因为内容较多,所以我放在在下周单独出来讲,今天的这篇就讲视图在整个Laravel的大体流程。

司机带你深入分析 Laravel 响应之视图

分析

我们进入到类Illuminate\Routing\RoutertoResponse方法:

司机带你深入分析 Laravel 响应之视图

因为我们的视图类Illuminate\View\View不符合上面的条件,所以代码会进入到我标出来的部分,所以这里生成了一个Illuminate\Http\Response类的对象,我们这里假设它为$response,根据老司机带你深入分析 Laravel 响应之一讲的,代码返回到public/index.php文件中,所以接下来它的send方法被调用,Illuminate\Http\Response类本身并没有实现send方法,但是它继承自Symfony\Component\HttpFoundation\Response类,它的父类实现了这个方法,我们来看:

司机带你深入分析 Laravel 响应之视图

sendHeaders方法的作用就是发送头部,这个我们在老司机带你深入分析 Laravel 响应之一讲过了,今天我们关心的是这个sendContent方法,但是大家要注意了,我们的子类Illuminate\Http\Response实现了sendContent方法,我们来看:

司机带你深入分析 Laravel 响应之视图

因为我们的控制器返回的是一个视图,也就是这里的参数$contentIlluminate\View\View类实现了Illuminate\Contracts\Support\Renderable接口,所以代码会进入到我标出来的代码中,所以接下来我们进入到Illuminate\View\View类的render方法中:

司机带你深入分析 Laravel 响应之视图

这里的参数$callback为null,首先调用renderContents在,这个是主角:

司机带你深入分析 Laravel 响应之视图

这个函数的代码中,只有getContents的调用对我们的分析是重要的,这个方法如下:

司机带你深入分析 Laravel 响应之视图

很好,分析到这里,你是不是好奇这里的engine属性是何时初始化的?没关系,老司机给你细细道来。

为了给大家讲解,我写了一个简单的控制器DebugController,如下:

司机带你深入分析 Laravel 响应之视图

它的debug方法调用了view方法生成了一个视图,我们来看view方法:

司机带你深入分析 Laravel 响应之视图

我们根据Illuminate\Contracts\View\Factory::class搜索一下Laravel代码,注意搜索的时候不要忘记命名空间,不然你会不劳而获的,很快,在Illuminate\Foundation\Application文件中(实际上这部分代码我们已经在之前的代码分析过了,不记得可以回过头去看),我们搜索到了结果:

司机带你深入分析 Laravel 响应之视图

Illuminate\Contracts\View\Factory::classview相关联,我们再搜索view,很快,我们在Illuminate\View\ViewServiceProvider中,我们找到了答案:

司机带你深入分析 Laravel 响应之视图

哈哈,就是它,既然来到了这个文件,我们有必要再看一下这个类的其它方法registerViewFinderregisterEngineResolver,这2个方法分别向容器绑定了view.finderview.engine.resolver,好了,我们registerFactory所注册的单例方法中,首先,从全局的容器中,获取了view.finderview.engine.resolverview.engine.resolver就是:

司机带你深入分析 Laravel 响应之视图

我们看一下注册的这个回调方法,首先生成了一个Illuminate\View\Engines\EngineResolver类的对象,接下来的foreach循环,我们只关心blade值,这里会调用registerBladeEngine方法:

司机带你深入分析 Laravel 响应之视图

上面的代码首先向容器中注册了一个名为blade.compiler的单例,紧接着调用了Illuminate\View\Engines\EngineResolver类的register方法,这个方法也很简单:

司机带你深入分析 Laravel 响应之视图

这个地方后面会用到,这里只是先说下,好了,经过这些分析我们知道view.engine.resolver就是Illuminate\View\Engines\EngineResolver类的实例对象。

我们再来看'view.finder'

司机带你深入分析 Laravel 响应之视图

这个就很简单了,Illuminate\View\FileViewFinder是一个视图文件寻找器,他会根据我们在config/view.php文件中的配置寻找视图文件,比如我的配置:

司机带你深入分析 Laravel 响应之视图

关于Illuminate\View\FileViewFinder不多说,很简单,大家有兴趣的自己去看哈。

经过爬山涉水,我们得到了view.finderview.engine.resolver这2个大爷,我们回到Illuminate\View\ViewServiceProviderregisterFactory方法中,继续看,紧接着调用当前类的createFactory方法:

司机带你深入分析 Laravel 响应之视图

这个方法也很简洁:

司机带你深入分析 Laravel 响应之视图

直接返回了一个\Illuminate\View\Factory类的对象,好了,我们已经得到了想要的$factory,返回到helpers.php文件中:

司机带你深入分析 Laravel 响应之视图

我们看\Illuminate\View\Factory类的make方法:

司机带你深入分析 Laravel 响应之视图

他这里调用到了viewInstance方法,这个方法如下:

司机带你深入分析 Laravel 响应之视图

我们看viewInstance方法:

司机带你深入分析 Laravel 响应之视图

直接返回一个Illuminate\View\View类的对象,但是我们来看看getEngineFromPath方法,这个方法根据视图文件的扩展名确定当前所要使用的模板引擎:

司机带你深入分析 Laravel 响应之视图

因为我么你的视图文件是blade文件,文件扩展名是blade.php,所以$engine就是blade,上面我们分析过了,所以这里的engines属性就是Illuminate\View\Engines\EngineResolver类的对象,我们看它的resolve方法:

司机带你深入分析 Laravel 响应之视图

还记得,我们在上面调用了它的register方法:

司机带你深入分析 Laravel 响应之视图

所以我们调用register方法会得到Illuminate\View\Engines\CompilerEngine类的对象,我们再一次回到\Illuminate\View\Factory类viewInstance方法中,这里我们在Illuminate\View\View类的构造函数中初始化了它的$engine属性。

司机带你深入分析 Laravel 响应之视图

明白了这个之后,我们可以再次回到Illuminate\View\View类的getContents方法了:

司机带你深入分析 Laravel 响应之视图

这里我简要的和大家说下gatherData方法,这个方法合并我们直接传递给视图的数据和我们的共享数据,共享数据是啥呢?还记不记得这个方法调用:

司机带你深入分析 Laravel 响应之视图

这个数据会在所有的模板中共享(看你的调用),gatherData方法的作用就是如此。

不多说,进入到Illuminate\View\Engines\CompilerEngine类的get方法:

司机带你深入分析 Laravel 响应之视图

它的代码首先就是判断当前视图是否过期,如果过期的话,就重新编译视图文件,关于视图文件的编译,我们在下周再来仔细讲,这里我们看看$compiler

司机带你深入分析 Laravel 响应之视图

所以他就是Illuminate\View\Compilers\BladeCompiler,关于Blade引擎,我们在下一篇博客中讲。

经过Blade引擎的编译,我们就得到了视图文件的内容,我们回到Illuminate\View\View类的render方法中,视图渲染的核心操作就算完成了,接下来的操作就和老司机带你深入分析 Laravel 响应之一中的一模一样了。

总结

作为Laravel视图系列的第一篇,希望大家仔细阅读,困难肯定是有的,但是读懂之后的喜悦也是无以言表的,加油。鄙人有个qq群,可以交流,也可以加我的微信,下方有,qq群如下:

本作品采用《CC 协议》,转载必须注明作者和本文链接
如果有不懂的地方,可以加我的qq:1174332406,或者是微信:itshardjs
本帖由系统于 9个月前 自动加精
Dennis_Ritchie
《L03 构架 API 服务器》
你将学到如 RESTFul 设计风格、PostMan 的使用、OAuth 流程,JWT 概念及使用 和 API 开发相关的进阶知识。
《L05 电商实战》
从零开发一个电商项目,功能包括电商后台、商品 & SKU 管理、购物车、订单管理、支付宝支付、微信支付、订单退款流程、优惠券等
讨论数量: 2

老哥放假这么早的吗

9个月前 评论
Dennis_Ritchie (楼主) 9个月前

讨论应以学习和精进为目的。请勿发布不友善或者负能量的内容,与人为善,比聪明更重要!