六、如何输出数据到终端
当执行完控制器中的方法响应数据给App类的run方法,直到这里就已经执行完了。
是不是有点懵这里的数据最终会返回哪里呢!
之前写过的框架执行流程、路由、控制器实例化都是从这里开始进入的。
所以当run方法执行完成之后,就会把对应的结果给返回到这里。
这一部分的代码Container::get('app')应该都知道了是返回一个App类的实例。
然后通过App类去执行run方法,才会有之前讲过的一切。
下图是咔咔从半中腰做的一个思维导图,前面的没有,后边的所有知识点都会写在这个思维导图里。
执行完run方法就会去执行Container::get('app')->run()->send()send这个方法,有多少人会认为在App类里边执行send方法。
其实不是的,回想一下之前执行控制器方法然后返回的响应结果是什么?
如果你不是很粗略的看都会记得是Response的一个对象实例。
所以说send方法会去response类里边去执行。
先不看其它的,先看这行代码$this->app['hook'],现在知道是执行的那里吗?
这种形式就是通过访问数组形式去访问对象的属性,也就是之前解析的ArrayAccess这个类。当访问的属性不存在时会去执行offsetGet,然后执行魔术方法__get,最终通过make方法返回实例,这一切的操作都是在容器中。
对这行代码具体是监听的什么就不去做解析了。
接着需要看处理输出数据的这行代码$data = $this->getContent();
这个方法做的事情就是将传过来的数据赋值给本类的content属性。
其实在获取输出数据这个方法中,请看咔咔圈出来的第一个地方感觉是很没有必要。
可以看到根本对数据就没有任何的处理,只是简单的返回了,所以说框架有好的地方也有不好的地方,只有你去阅读了才会知道,否则你会对你经常使用的工具一无所知。
在接着就是Trace调试注入,就是通过配置文件配置的,通过调用debug类实现的,这里就不详解了。
然后就是缓存判断,缓存会在后文中单独拎出来讲,所以也是过。
在接下来就对响应头的设置了,检测 HTTP 头是否已经发送,这块的东西就很重要了,也是平时接触不多的知识点了。
- headers_sent() : 检测 HTTP 头是否已经发送
- http_response_code() :获取/设置响应的 HTTP 状态码
- header : 函数向客户端发送原始的 HTTP 报头。
最后一步,来了来了,它来了,它带着echo来了,执行了一个方法$this->sendData($data);
给人一种媳妇熬成娘的感觉,终于来到的终点站,一个echo输出了咔咔几十天的心酸啊!
为了到达这个echo咔咔是经历九九八十一难啊!战斗还未停止,同志仍需努力啊!
那么到这里关于框架执行然后到应用初始化,在到路由检测、控制器的实例化、然后返回response实例,在通过入口文件执行send方法。
最后将数据输出到终端,也就是一个echo的事情。
虽然这里的战斗结束了,但是在下面还有一个非常重要的知识点,咔咔将重新提一节来进行说明。
七、fastcgi_finish_request方法巧用
在上一节中通过Container::get('app')->run()->send();在response类中执行了send方法,输出了数据。
但是在输出数据之后还执行了一个方法fastcgi_finish_request();,给的注释是提高页面响应,接下来好好来扒一扒其中的奥秘。
在PHP官网中看到这样一段话
The script will still occupy a FPM process after fastcgi_finish_request(). So using it excessively for long running tasks may occupy all your FPM threads up to pm.max_children. This will lead to gateway errors on the webserver.
在fastcgi_finish_request()之后,脚本仍将占用FPM进程。 因此,对于长时间运行的任务过度使用它可能会占用您的所有FPM线程,直到pm.max_children。 这将导致Web服务器上的网关错误。
所以说在没有彻底的了解这个方法之前不要轻易的在自己的项目中使用这个方法。
接下来咔咔将使用一个案例来演示这个方法的使用,仅仅只是演示使用,如果需要使用到项目中请仔细阅读文档应该注意的问题。
案例演示
公司有一个业务需要发送通知给用户,但是由于发送时间太久,非常费时间,有可能需要好几十秒的时间,更严重的会直接导致浏览器连接超时。
在一个问题就是用户体验的问题,用户等待时间过程,体验当然不好。
为了解决以上俩个问题,今天谈论的fastcgi_finish_request就派上了用场。
理解
对这个函数的理解其实就是发送响应给浏览器,用户等待时间大大缩短,但是PHP进程还是在运行的。
这样就达到了来个目的,就类似于我们经常说的异步执行。
直观的来说就是发送邮件有可能需要10秒,但是用户是没有感知的,用户点击发送邮件之后直接就返回发送成功,浏览器响应结束,用户做其它事情,后台进程继续执行发送邮件的任务。
案例