老司机带你深入分析 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
本帖由系统于 4年前 自动加精
Dennis_Ritchie
《L04 微信小程序从零到发布》
从小程序个人账户申请开始,带你一步步进行开发一个微信小程序,直到提交微信控制台上线发布。
《G01 Go 实战入门》
从零开始带你一步步开发一个 Go 博客项目,让你在最短的时间内学会使用 Go 进行编码。项目结构很大程度上参考了 Laravel。
讨论数量: 6

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

4年前 评论

老司机继续讲php啊..

4年前 评论

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

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

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

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

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

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

能力越大,责任越大

4年前 评论

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

网络不缺喷子

4年前 评论

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