老司机带你深入分析 Laravel 响应之 JSON

前言#

本来在上一篇博客中,我已经决定不再写关于 Laravel 源代码的文章了,但是上周六突然无缘无故被喷了一波(我也很懵逼,哪里都有这种奇葩,这都能被喷),所以这周我继续讲下去。这篇要讲的内容承接自上一篇《老死机带你深入理解 Laravel 之验证器下
》,所以如果你要阅读本篇博文,请自行阅读上一篇。

Laravel响应之深入分析

我们直接来到类 Illuminate\Routing\RouterrunRouteWithinStack 方法(如果不清楚,所以我建议你看《老死机带你深入理解 Laravel 之验证器下
》):

Laravel响应之深入分析

$route->run() 就是我们控制器的返回结果,比如我的 DebugControllerdebug 方法如下:

Laravel响应之深入分析

当我访问这个方法时候,我们来测试一下,我们打印 $route->run() 的值,浏览器结果:

Laravel响应之深入分析

这里调用了 prepareResponse 方法,它继续调用 toResponse 方法,该方法如下:

Laravel响应之深入分析

因为在我们的控制器中,返回的是一个数组,所以我们沿着这条线索进行分析(其它情况,后面再行分析),此时的 $response 就是 Illuminate\Http\JsonResponse 类的对象,紧接着调用 prepare 方法,Illuminate\Http\JsonResponse 类继承自 Symfony\Component\HttpFoundation\JsonResponse 类,Symfony\Component\HttpFoundation\JsonResponse 类又继承自 Symfony\Component\HttpFoundation\Response 类,继承关系并不复杂,代码量也不大,自己有兴趣的可以看哈。

前面说的 prepare 方法就属于 Symfony\Component\HttpFoundation\Response 类的,我不打算分析这个方法,这个方法的作用就是设置响应的 HTTP 头部,比如:Content-Type 等。

经过了上面和之前几篇的一系列分析,我们得到了 $response 响应对象,我们回到 Laravel 的入口文件 public/index.php 文件中:

Laravel响应之深入分析

这个时候,你可以打印下 $response 的类(比如:dd(get_class($response))):

Laravel响应之深入分析

继续分析响应对象的 send 方法,这个方法也属于 Symfony\Component\HttpFoundation\Response 类,很简单:

Laravel响应之深入分析

方法 sendHeaders 用于发送头部,如下:

Laravel响应之深入分析

方法 sendContent 用于发送响应的内容:

Laravel响应之深入分析

哈哈,就是这么简单粗暴。

send 方法调用完之后,回到 index.php 文件中:

Laravel响应之深入分析

$kernel 就是 Illuminate\Foundation\Http\Kernel 类的对象,下面进入到 terminate 方法中:

Laravel响应之深入分析

方法 terminateMiddleware 用于运行我们定义的中间件:

Laravel响应之深入分析

如果你认真的阅读过我之前写的几篇《老死机带你深入理解 Laravel 之验证器上(控制器参数解析)》和《老死机带你深入理解 Laravel 之验证器下》,就知道这段代码已经讲过了,只是要提醒你的是每一个中间件都可以实现 terminate 方法,这个方法在响应被发送给客户端之后,会被调用。

回到 terminate 方法中,调用 $this->app->terminate() 方法,app 就是 Illuminate\Foundation\Application 类的对象:

Laravel响应之深入分析

terminatingCallbacks 中的每一个元素都是一个回调,我们可以通过调用 appterminate 方法添加回调。

总结#

我的天哪,终于简要的走完了 laravel 的流程,但这是远远不够的,因为我这里分析的是控制器返回的是数组类型,在后面的章节中,我会给大家分析其它的类型,包括视图,三人行,必有我师焉,可以加入 QQ 群,进行讨论:

本作品采用《CC 协议》,转载必须注明作者和本文链接
微信:okayGoHome
本帖由系统于 5年前 自动加精
Dennis_Ritchie
《L04 微信小程序从零到发布》
从小程序个人账户申请开始,带你一步步进行开发一个微信小程序,直到提交微信控制台上线发布。
《L02 从零构建论坛系统》
以构建论坛项目 LaraBBS 为线索,展开对 Laravel 框架的全面学习。应用程序架构思路贴近 Laravel 框架的设计哲学。
讨论数量: 6

我正在从头开始看你的文章,强烈支持继续更新下去。

5年前 评论

老司机继续讲 php 啊..

5年前 评论

文章写的很好,这里有个不成熟的小建议,深入分析可以讲的深入一点嘛。就是出了这种调用链以外,每次给大家讲个稍微深点的知识点。

比如就像你说的 terminate 方法在响应被发送给客户端之后,会被调用。那么大家肯定好奇,一般 php 开发,响应都是结束的最后一步,发送了响应还可以处理其他事情,那就让 php 能做更多的事情了。那么 terminate 有是怎么实现的呢

跟踪代码可以发现,terminate 并不是 echo 之后,就马上能响应给客户端。而是通过一个 fastcgi_finish_request 的方法来实现的,这个方法仔细一看,是 fpm 的方法。那么是不是用了 nginx 才能使用 terminate 啊?

肯定是 nginx 才能使用 fpm 这特性和方法啊,要做到类似的效果,可以用队列。在使用 fpm 情况下,队列也可以做 terminate 能做的事,那孰优孰劣呢?等等 terminate 是运行在 fpm 进程上,那么 terminate 在运行时间稍长一点的话,是不是会超时?

相信大牛如你能带来更多更好的文章,加油

5年前 评论
Dennis_Ritchie (楼主) 5年前
golang练习生 5年前

能力越大,责任越大

5年前 评论

但是上周六突然无缘无故被喷了一波(我也很懵逼,哪里都有这种奇葩,这都能被喷)

网络不缺喷子

5年前 评论