0

0

Symfony2源码分析——启动过程2,symfony2源码_PHP教程

php中文网

php中文网

发布时间:2016-07-13 10:15:59

|

1097人浏览过

|

来源于php中文网

原创

symfony2源码分析——启动过程2,symfony2源码

  上一篇分析symfony2框架源码,探究symfony2如何完成一个请求的前半部分,前半部分可以理解为symfony2框架为处理请求做准备工作,包括container生成、缓存、bundls初始化等一些列准备工作(symfony2源码分析——启动过程1)。而这一篇讲的是symfony2如何根据请求的数据生成response对象,向客户端返回响应数据。

  在分析前需要了解Symfony2的事件驱动机制:Symfony2事件驱动。

  言归正传,Symfony2请求的工作流程其实是Symfony2内核的事件驱动完成的,下面是Symfony2框架定义好的内核事件:

Symfony2源码分析——启动过程2,symfony2源码_PHP教程final class KernelEvents { /** * The REQUEST event occurs at the very beginning of request * dispatching * * This event allows you to create a response for a request before any * other code in the framework is executed. The event listener method * receives a Symfony\Component\HttpKernel\Event\GetResponseEvent * instance. * * @var string * * @api */ const REQUEST = 'kernel.request'; /** * The EXCEPTION event occurs when an uncaught exception appears * * This event allows you to create a response for a thrown exception or * to modify the thrown exception. The event listener method receives * a Symfony\Component\HttpKernel\Event\GetResponseForExceptionEvent * instance. * * @var string * * @api */ const EXCEPTION = 'kernel.exception'; /** * The VIEW event occurs when the return value of a controller * is not a Response instance * * This event allows you to create a response for the return value of the * controller. The event listener method receives a * Symfony\Component\HttpKernel\Event\GetResponseForControllerResultEvent * instance. * * @var string * * @api */ const VIEW = 'kernel.view'; /** * The CONTROLLER event occurs once a controller was found for * handling a request * * This event allows you to change the controller that will handle the * request. The event listener method receives a * Symfony\Component\HttpKernel\Event\FilterControllerEvent instance. * * @var string * * @api */ const CONTROLLER = 'kernel.controller'; /** * The RESPONSE event occurs once a response was created for * replying to a request * * This event allows you to modify or replace the response that will be * replied. The event listener method receives a * Symfony\Component\HttpKernel\Event\FilterResponseEvent instance. * * @var string * * @api */ const RESPONSE = 'kernel.response'; /** * The TERMINATE event occurs once a response was sent * * This event allows you to run expensive post-response jobs. * The event listener method receives a * Symfony\Component\HttpKernel\Event\PostResponseEvent instance. * * @var string */ const TERMINATE = 'kernel.terminate'; /** * The FINISH_REQUEST event occurs when a response was generated for a request. * * This event allows you to reset the global and environmental state of * the application, when it was changed during the request. * * @var string */ const FINISH_REQUEST = 'kernel.finish_request'; } View Code

  我们可以编写事件监听器,监听相应的内核事件,在Symfony2触发该事件的时候,相应的事件监听器就会执行。监听和唤醒形象的描述,就像,你(事件监听器)参加校运会,去大会(Symfony2)登记(监听)参加50米短跑(事件),当50米短跑比赛开始了(事件被触发),那你就奔跑吧(监听器执行,其实就是一个执行函数,函数完成什么工作就取决于你的需求了),少年。

  Symfony2的内核事件处理流程大部分工作都在HttpKernel::handleRaw方法中:

立即学习PHP免费学习笔记(深入)”;

一点PPT
一点PPT

一句话生成专业PPT,AI自动排版配图

下载
<span> 1</span>     <span>private</span> function handleRaw(Request $request, $type =<span> self::MASTER_REQUEST)
</span><span> 2</span> <span>    {
</span><span> 3</span>         $<span>this</span>->requestStack-><span>push($request);
</span><span> 4</span> 
<span> 5</span>         <span>//</span><span> request
</span><span> 6</span>         <span>//</span><span> 初始化事件,事件对象会被传递给监听器,所以事件可以说是一个信息的载体,事件内存放着监听器感兴趣的数据。</span>
<span> 7</span>         $<span>event</span> = <span>new</span> GetResponseEvent($<span>this</span><span>, $request, $type);
</span><span> 8</span>         <span>//</span><span> 触发kernel.request事件,后续详细讲解EventDispatcher::dispatch方法的实现,
</span><span> 9</span>         <span>//</span><span> 这里我们需要知道的是,dispatcher把$event传递给所有监听了kernel.request事件的监听器,监听器将会执行。
</span><span>10</span>         <span>//</span><span> kernel.request事件发生在controller执行之前,我们可以在这一步奏完成路由解析等为controller执行提供准备数据,
</span><span>11</span>         <span>//</span><span> 在这个过程允许我们直接生成Response对象,向客户端输出数据,那么controller就不会被执行了。</span>
<span>12</span>         $<span>this</span>->dispatcher->dispatch(KernelEvents::REQUEST, $<span>event</span><span>);
</span><span>13</span> 
<span>14</span>         <span>//</span><span> 如果我们在kernel.request事件生成了Response对象(响应数据),那么就跳过kernel.controller、kernel.view事件、
</span><span>15</span>         <span>//</span><span> controller也会被跳过,直接执行kernel.response事件。</span>
<span>16</span>         <span>if</span> ($<span>event</span>-><span>hasResponse()) {
</span><span>17</span>             <span>return</span> $<span>this</span>->filterResponse($<span>event</span>-><span>getResponse(), $request, $type);
</span><span>18</span> <span>        }
</span><span>19</span> 
<span>20</span>         <span>//</span><span> load controller
</span><span>21</span>         <span>//</span><span> 根据路由规则返回 一个对象或者数组或者字符串 ,如果$controller是一个数组,$controller[0]是存放的是要执行的controller对象,
</span><span>22</span>         <span>//</span><span> $controller[0]存放的是controller对象执行的方法,即action,方法的参数没有保存在$controller数组中;
</span><span>23</span>         <span>//</span><span> 如果$controller是对象,那么该对象就实现了__invoke 方法;
</span><span>24</span>         <span>//</span><span> 如果$controller是字符串,那么$controller就是要运行的函数的函数名。
</span><span>25</span>         <span>//</span><span> 图2是$controller的一个var_dump例子</span>
<span>26</span>         <span>if</span> (<span>false</span> === $controller = $<span>this</span>->resolver-><span>getController($request)) {
</span><span>27</span>             <span>throw</span> <span>new</span> NotFoundHttpException(sprintf(<span>'</span><span>Unable to find the controller for path "%s". Maybe you forgot to add the matching route in your routing configuration?</span><span>'</span>, $request-><span>getPathInfo()));
</span><span>28</span> <span>        }
</span><span>29</span> 
<span>30</span>         $<span>event</span> = <span>new</span> FilterControllerEvent($<span>this</span><span>, $controller, $request, $type);
</span><span>31</span>         <span>//</span><span> 触发kernel.controller事件,这个事件发生在controller执行前。我们可以通过监听这个事件在controller执行前修改controller,
</span><span>32</span>         <span>//</span><span> 或者完成一些动作。</span>
<span>33</span>         $<span>this</span>->dispatcher->dispatch(KernelEvents::CONTROLLER, $<span>event</span><span>);
</span><span>34</span>         $controller = $<span>event</span>-><span>getController();
</span><span>35</span> 
<span>36</span>         <span>//</span><span> controller arguments
</span><span>37</span>         <span>//</span><span> 从request对象中获取controller方法的参数</span>
<span>38</span>         $arguments = $<span>this</span>->resolver-><span>getArguments($request, $controller);
</span><span>39</span> 
<span>40</span>         <span>//</span><span> call controller
</span><span>41</span>         <span>//</span><span> 执行controller</span>
<span>42</span>         $response =<span> call_user_func_array($controller, $arguments);
</span><span>43</span> 
<span>44</span>         <span>//</span><span> view
</span><span>45</span>         <span>//</span><span> 如果$response不是Response对象,那么kernel.view事件就会触发,监听kernel.view事件的监听器通过$response值生成Response对象。</span>
<span>46</span>         <span>if</span> (!<span>$response instanceof Response) {
</span><span>47</span>             $<span>event</span> = <span>new</span> GetResponseForControllerResultEvent($<span>this</span><span>, $request, $type, $response);
</span><span>48</span>             $<span>this</span>->dispatcher->dispatch(KernelEvents::VIEW, $<span>event</span><span>);
</span><span>49</span> 
<span>50</span>             <span>if</span> ($<span>event</span>-><span>hasResponse()) {
</span><span>51</span>                 $response = $<span>event</span>-><span>getResponse();
</span><span>52</span> <span>            }
</span><span>53</span> 
<span>54</span>             <span>if</span> (!<span>$response instanceof Response) {
</span><span>55</span>                 $msg = sprintf(<span>'</span><span>The controller must return a response (%s given).</span><span>'</span>, $<span>this</span>-><span>varToString($response));
</span><span>56</span> 
<span>57</span>                 <span>//</span><span> the user may have forgotten to return something</span>
<span>58</span>                 <span>if</span> (<span>null</span> ===<span> $response) {
</span><span>59</span>                     $msg .= <span>'</span><span> Did you forget to add a return statement somewhere in your controller?</span><span>'</span><span>;
</span><span>60</span> <span>                }
</span><span>61</span>                 <span>throw</span> <span>new</span><span> \LogicException($msg);
</span><span>62</span> <span>            }
</span><span>63</span> <span>        }
</span><span>64</span> 
<span>65</span>         <span>//</span><span> 触发kernel.response事件,在向客户端输出Response对象前,我们可以对Response对象进行修改,
</span><span>66</span>         <span>//</span><span> 例如修改response头部,设置缓存、压缩输出数据等。
</span><span>67</span> 
<span>68</span>         <span>//</span><span> 接着触发kernel.finish_request事件,把当前请求从请求栈中弹出,当前请求就完成。</span>
<span>69</span>         <span>return</span> $<span>this</span>-><span>filterResponse($response, $request, $type);
</span><span>70</span> 
<span>71</span>         <span>//</span><span> 千万别忘记了,filterResponse执行完后,Symfony2内核事件处理流程还有最后一步,位于app_dev.php[app.php]最后一行,
</span><span>72</span>         <span>//</span><span> $kernel->terminate($request, $response);这个方法触发kernel.terminate事件,此时,Symfony2已经响应了客户端的请求,
</span><span>73</span>         <span>//</span><span> 向客户端输出了Response对象。监听kernel.terminate事件的监听器,主要是为了完成一些耗时的操作,操作的结果不需要返回给
</span><span>74</span>         <span>//</span><span> 客户端的,例如邮件发送、图片压缩等等。
</span><span>75</span>         <span>//</span><span> 到这里,Symfony2的整个流程就走完了。</span>
<span>76</span>     }
<span>HttpKernel::filterResponse方法和</span>HttpKernel::finishRequest方法:
Symfony2源码分析——启动过程2,symfony2源码_PHP教程 1 private function filterResponse(Response $response, Request $request, $type) 2 { 3 $event = new FilterResponseEvent($this, $request, $type, $response); 4 5 $this->dispatcher->dispatch(KernelEvents::RESPONSE, $event); 6 7 $this->finishRequest($request, $type); 8 9 return $event->getResponse(); 10 } 11 12 /** 13 * Publishes the finish request event, then pop the request from the stack. 14 * 15 * Note that the order of the operations is important here, otherwise 16 * operations such as {@link RequestStack::getParentRequest()} can lead to 17 * weird results. 18 * 19 * @param Request $request 20 * @param int $type 21 */ 22 private function finishRequest(Request $request, $type) 23 { 24 $this->dispatcher->dispatch(KernelEvents::FINISH_REQUEST, new FinishRequestEvent($this, $request, $type)); 25 $this->requestStack->pop(); 26 } View Code

图2

Symfony2框架的事件分发机制的核心代码:

<span> 1</span>     <span>public</span> function dispatch($eventName, Event $<span>event</span> = <span>null</span><span>)
</span><span> 2</span> <span>    {
</span><span> 3</span>         <span>if</span> (<span>null</span> === $<span>event</span><span>) {
</span><span> 4</span>             $<span>event</span> = <span>new</span><span> Event();
</span><span> 5</span> <span>        }
</span><span> 6</span> 
<span> 7</span>         $<span>event</span>->setDispatcher($<span>this</span><span>);
</span><span> 8</span>         $<span>event</span>-><span>setName($eventName);
</span><span> 9</span> 
<span>10</span>         <span>if</span> (!isset($<span>this</span>-><span>listeners[$eventName])) {
</span><span>11</span>             <span>return</span> $<span>event</span><span>;
</span><span>12</span> <span>        }
</span><span>13</span> 
<span>14</span>         <span>//</span><span> $eventName即:KernelEvents::REQUEST、KernelEvents::CONTROLLER、KernelEvents::VIEW、KernelEvents::RESPONSE、KernelEvents::TERMINATE等
</span><span>15</span>         <span>//</span><span> getListeners返回所有监听$eventName事件的监听器</span>
<span>16</span>         $<span>this</span>->doDispatch($<span>this</span>->getListeners($eventName), $eventName, $<span>event</span><span>);
</span><span>17</span> 
<span>18</span>         <span>return</span> $<span>event</span><span>;
</span><span>19</span> <span>    }
</span><span>20</span> 
<span>21</span>     <span>protected</span> function doDispatch($listeners, $eventName, Event $<span>event</span><span>)
</span><span>22</span> <span>    {
</span><span>23</span>         <span>//</span><span> 监听器执行</span>
<span>24</span>         <span>foreach</span> ($listeners <span>as</span><span> $listener) {
</span><span>25</span>             call_user_func($listener, $<span>event</span>, $eventName, $<span>this</span><span>);
</span><span>26</span>             <span>//</span><span> 如果其中一个监听器把$event的propagationStopped属性设置为true,那么表示$eventName这一事件终止执行,
</span><span>27</span>             <span>//</span><span> 事件不会往$listeners里尚未执行的监听器传递该事件。</span>
<span>28</span>             <span>if</span> ($<span>event</span>-><span>isPropagationStopped()) {
</span><span>29</span>                 <span>break</span><span>;
</span><span>30</span> <span>            }
</span><span>31</span> <span>        }
</span><span>32</span>     }

 

有没有哪本书具体讲linux内核启动过程的,详细点的(最好具体到实际代码),最好内核针对于26以后的

我个人感觉毛德操先生的书linux内核情景分析,分析的很透彻的,对整个Linux内核的讲解很不错.具体到启动过程,这个启动过程很泛的,你只需要知道整体的启动过程,其他的细节,还得看内核源码讲解,所以,推荐你看点博客了解下启动大体过程,具体到每个细节,看linux内核情景分析吧.
 

android 21的源码分析之长按电源键弹出对话框功可以更改

1.这个dialog是由PhoneWindowManager控制的,在PhoneWindowManager的interceptKeyTq方法中,代码是这一行

mHandler.postDelayed(mPowerLongPress, ViewConfiguration.getGlobalActionKeyTimeout());

mProwerLongPress是一个Runnable,执行时调用GlobalActions中的showDialog方法。所以这个dialog是由GlobalActions管理的,PowerDialog是之前版本中的,现在已经弃用了。

2.可以在GlobalActions中createDialog方法中mSilentModeToggle action的onToggle方法中加入

mAudioManager.setVibrateSetting(AudioManager.VIBRATE_TYPE_RINGER, on ? AudioManager.VIBRATE_SETTING_ON : AudioManager.VIBRATE_SETTING_OFF);

这一句,仿照铃声的处理,应该没问题,不过没试所以也不能确定。

希望对你有帮助。
 

www.bkjia.comtruehttp://www.bkjia.com/PHPjc/899447.htmlTechArticleSymfony2源码分析——启动过程2,symfony2源码 上一篇分析Symfony2框架源码,探究Symfony2如何完成一个请求的前半部分,前半部分可以理解为Sy...

相关文章

PHP速学教程(入门到精通)
PHP速学教程(入门到精通)

PHP怎么学习?PHP怎么入门?PHP在哪学?PHP怎么学才快?不用担心,这里为大家提供了PHP速学教程(入门到精通),有需要的小伙伴保存下载就能学习啦!

下载

本站声明:本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系admin@php.cn

热门AI工具

更多
DeepSeek
DeepSeek

幻方量化公司旗下的开源大模型平台

豆包大模型
豆包大模型

字节跳动自主研发的一系列大型语言模型

WorkBuddy
WorkBuddy

腾讯云推出的AI原生桌面智能体工作台

腾讯元宝
腾讯元宝

腾讯混元平台推出的AI助手

文心一言
文心一言

文心一言是百度开发的AI聊天机器人,通过对话可以生成各种形式的内容。

讯飞写作
讯飞写作

基于讯飞星火大模型的AI写作工具,可以快速生成新闻稿件、品宣文案、工作总结、心得体会等各种文文稿

即梦AI
即梦AI

一站式AI创作平台,免费AI图片和视频生成。

ChatGPT
ChatGPT

最最强大的AI聊天机器人程序,ChatGPT不单是聊天机器人,还能进行撰写邮件、视频脚本、文案、翻译、代码等任务。

相关专题

更多
TypeScript类型系统进阶与大型前端项目实践
TypeScript类型系统进阶与大型前端项目实践

本专题围绕 TypeScript 在大型前端项目中的应用展开,深入讲解类型系统设计与工程化开发方法。内容包括泛型与高级类型、类型推断机制、声明文件编写、模块化结构设计以及代码规范管理。通过真实项目案例分析,帮助开发者构建类型安全、结构清晰、易维护的前端工程体系,提高团队协作效率与代码质量。

26

2026.03.13

Python异步编程与Asyncio高并发应用实践
Python异步编程与Asyncio高并发应用实践

本专题围绕 Python 异步编程模型展开,深入讲解 Asyncio 框架的核心原理与应用实践。内容包括事件循环机制、协程任务调度、异步 IO 处理以及并发任务管理策略。通过构建高并发网络请求与异步数据处理案例,帮助开发者掌握 Python 在高并发场景中的高效开发方法,并提升系统资源利用率与整体运行性能。

46

2026.03.12

C# ASP.NET Core微服务架构与API网关实践
C# ASP.NET Core微服务架构与API网关实践

本专题围绕 C# 在现代后端架构中的微服务实践展开,系统讲解基于 ASP.NET Core 构建可扩展服务体系的核心方法。内容涵盖服务拆分策略、RESTful API 设计、服务间通信、API 网关统一入口管理以及服务治理机制。通过真实项目案例,帮助开发者掌握构建高可用微服务系统的关键技术,提高系统的可扩展性与维护效率。

178

2026.03.11

Go高并发任务调度与Goroutine池化实践
Go高并发任务调度与Goroutine池化实践

本专题围绕 Go 语言在高并发任务处理场景中的实践展开,系统讲解 Goroutine 调度模型、Channel 通信机制以及并发控制策略。内容包括任务队列设计、Goroutine 池化管理、资源限制控制以及并发任务的性能优化方法。通过实际案例演示,帮助开发者构建稳定高效的 Go 并发任务处理系统,提高系统在高负载环境下的处理能力与稳定性。

51

2026.03.10

Kotlin Android模块化架构与组件化开发实践
Kotlin Android模块化架构与组件化开发实践

本专题围绕 Kotlin 在 Android 应用开发中的架构实践展开,重点讲解模块化设计与组件化开发的实现思路。内容包括项目模块拆分策略、公共组件封装、依赖管理优化、路由通信机制以及大型项目的工程化管理方法。通过真实项目案例分析,帮助开发者构建结构清晰、易扩展且维护成本低的 Android 应用架构体系,提升团队协作效率与项目迭代速度。

92

2026.03.09

JavaScript浏览器渲染机制与前端性能优化实践
JavaScript浏览器渲染机制与前端性能优化实践

本专题围绕 JavaScript 在浏览器中的执行与渲染机制展开,系统讲解 DOM 构建、CSSOM 解析、重排与重绘原理,以及关键渲染路径优化方法。内容涵盖事件循环机制、异步任务调度、资源加载优化、代码拆分与懒加载等性能优化策略。通过真实前端项目案例,帮助开发者理解浏览器底层工作原理,并掌握提升网页加载速度与交互体验的实用技巧。

102

2026.03.06

Rust内存安全机制与所有权模型深度实践
Rust内存安全机制与所有权模型深度实践

本专题围绕 Rust 语言核心特性展开,深入讲解所有权机制、借用规则、生命周期管理以及智能指针等关键概念。通过系统级开发案例,分析内存安全保障原理与零成本抽象优势,并结合并发场景讲解 Send 与 Sync 特性实现机制。帮助开发者真正理解 Rust 的设计哲学,掌握在高性能与安全性并重场景中的工程实践能力。

227

2026.03.05

PHP高性能API设计与Laravel服务架构实践
PHP高性能API设计与Laravel服务架构实践

本专题围绕 PHP 在现代 Web 后端开发中的高性能实践展开,重点讲解基于 Laravel 框架构建可扩展 API 服务的核心方法。内容涵盖路由与中间件机制、服务容器与依赖注入、接口版本管理、缓存策略设计以及队列异步处理方案。同时结合高并发场景,深入分析性能瓶颈定位与优化思路,帮助开发者构建稳定、高效、易维护的 PHP 后端服务体系。

532

2026.03.04

AI安装教程大全
AI安装教程大全

2026最全AI工具安装教程专题:包含各版本AI绘图、AI视频、智能办公软件的本地化部署手册。全篇零基础友好,附带最新模型下载地址、一键安装脚本及常见报错修复方案。每日更新,收藏这一篇就够了,让AI安装不再报错!

171

2026.03.04

热门下载

更多
网站特效
/
网站源码
/
网站素材
/
前端模板

精品课程

更多
相关推荐
/
热门推荐
/
最新课程
Git 教程
Git 教程

共21课时 | 4.2万人学习

Git版本控制工具
Git版本控制工具

共8课时 | 1.6万人学习

Git中文开发手册
Git中文开发手册

共0课时 | 94人学习

关于我们 免责申明 举报中心 意见反馈 讲师合作 广告合作 最新更新
php中文网:公益在线php培训,帮助PHP学习者快速成长!
关注服务号 技术交流群
PHP中文网订阅号
每天精选资源文章推送

Copyright 2014-2026 https://www.php.cn/ All Rights Reserved | php.cn | 湘ICP备2023035733号