国产探花免费观看_亚洲丰满少妇自慰呻吟_97日韩有码在线_资源在线日韩欧美_一区二区精品毛片,辰东完美世界有声小说,欢乐颂第一季,yy玄幻小说排行榜完本

首頁 > 學院 > 開發(fā)設(shè)計 > 正文

Symfony2源碼分析——啟動過程2

2019-11-15 01:52:43
字體:
供稿:網(wǎng)友
Symfony2源碼分析——啟動過程2

  文章地址:http://www.hcoding.com/?p=46

  上一篇分析Symfony2框架源碼,探究Symfony2如何完成一個請求的前半部分,前半部分可以理解為Symfony2框架為處理請求做準備工作,包括container生成、緩存、bundls初始化等一些列準備工作(Symfony2源碼分析——啟動過程1)。而這一篇講的是Symfony2如何根據(jù)請求的數(shù)據(jù)生成Response對象,向客戶端返回響應(yīng)數(shù)據(jù)。

  在分析前需要了解Symfony2的事件驅(qū)動機制:Symfony2事件驅(qū)動。

  言歸正傳,Symfony2請求的工作流程其實是Symfony2內(nèi)核的事件驅(qū)動完成的,下面是Symfony2框架定義好的內(nèi)核事件:

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

  我們可以編寫事件監(jiān)聽器,監(jiān)聽相應(yīng)的內(nèi)核事件,在Symfony2觸發(fā)該事件的時候,相應(yīng)的事件監(jiān)聽器就會執(zhí)行。監(jiān)聽和喚醒形象的描述,就像,你(事件監(jiān)聽器)參加校運會,去大會(Symfony2)登記(監(jiān)聽)參加50米短跑(事件),當50米短跑比賽開始了(事件被觸發(fā)),那你就奔跑吧(監(jiān)聽器執(zhí)行,其實就是一個執(zhí)行函數(shù),函數(shù)完成什么工作就取決于你的需求了),少年。

  Symfony2的內(nèi)核事件處理流程大部分工作都在HttpKernel::handleRaw方法中:

 1     PRivate function handleRaw(Request $request, $type = self::MASTER_REQUEST) 2     { 3         $this->requestStack->push($request); 4  5         // request 6         // 初始化事件,事件對象會被傳遞給監(jiān)聽器,所以事件可以說是一個信息的載體,事件內(nèi)存放著監(jiān)聽器感興趣的數(shù)據(jù)。 7         $event = new GetResponseEvent($this, $request, $type); 8         // 觸發(fā)kernel.request事件,后續(xù)詳細講解EventDispatcher::dispatch方法的實現(xiàn), 9         // 這里我們需要知道的是,dispatcher把$event傳遞給所有監(jiān)聽了kernel.request事件的監(jiān)聽器,監(jiān)聽器將會執(zhí)行。10         // kernel.request事件發(fā)生在controller執(zhí)行之前,我們可以在這一步奏完成路由解析等為controller執(zhí)行提供準備數(shù)據(jù),11         // 在這個過程允許我們直接生成Response對象,向客戶端輸出數(shù)據(jù),那么controller就不會被執(zhí)行了。12         $this->dispatcher->dispatch(KernelEvents::REQUEST, $event);13 14         // 如果我們在kernel.request事件生成了Response對象(響應(yīng)數(shù)據(jù)),那么就跳過kernel.controller、kernel.view事件、15         // controller也會被跳過,直接執(zhí)行kernel.response事件。16         if ($event->hasResponse()) {17             return $this->filterResponse($event->getResponse(), $request, $type);18         }19 20         // load controller21         // 根據(jù)路由規(guī)則返回 一個對象或者數(shù)組或者字符串 ,如果$controller是一個數(shù)組,$controller[0]是存放的是要執(zhí)行的controller對象,22         // $controller[0]存放的是controller對象執(zhí)行的方法,即action,方法的參數(shù)沒有保存在$controller數(shù)組中;23         // 如果$controller是對象,那么該對象就實現(xiàn)了__invoke 方法;24         // 如果$controller是字符串,那么$controller就是要運行的函數(shù)的函數(shù)名。25         // 圖2是$controller的一個var_dump例子26         if (false === $controller = $this->resolver->getController($request)) {27             throw new NotFoundHttpException(sprintf('Unable to find the controller for path "%s". Maybe you forgot to add the matching route in your routing configuration?', $request->getPathInfo()));28         }29 30         $event = new FilterControllerEvent($this, $controller, $request, $type);31         // 觸發(fā)kernel.controller事件,這個事件發(fā)生在controller執(zhí)行前。我們可以通過監(jiān)聽這個事件在controller執(zhí)行前修改controller,32         // 或者完成一些動作。33         $this->dispatcher->dispatch(KernelEvents::CONTROLLER, $event);34         $controller = $event->getController();35 36         // controller arguments37         // 從request對象中獲取controller方法的參數(shù)38         $arguments = $this->resolver->getArguments($request, $controller);39 40         // call controller41         // 執(zhí)行controller42         $response = call_user_func_array($controller, $arguments);43 44         // view45         // 如果$response不是Response對象,那么kernel.view事件就會觸發(fā),監(jiān)聽kernel.view事件的監(jiān)聽器通過$response值生成Response對象。46         if (!$response instanceof Response) {47             $event = new GetResponseForControllerResultEvent($this, $request, $type, $response);48             $this->dispatcher->dispatch(KernelEvents::VIEW, $event);49 50             if ($event->hasResponse()) {51                 $response = $event->getResponse();52             }53 54             if (!$response instanceof Response) {55                 $msg = sprintf('The controller must return a response (%s given).', $this->varToString($response));56 57                 // the user may have forgotten to return something58                 if (null === $response) {59                     $msg .= ' Did you forget to add a return statement somewhere in your controller?';60                 }61                 throw new /LogicException($msg);62             }63         }64 65         // 觸發(fā)kernel.response事件,在向客戶端輸出Response對象前,我們可以對Response對象進行修改,66         // 例如修改response頭部,設(shè)置緩存、壓縮輸出數(shù)據(jù)等。67 68         // 接著觸發(fā)kernel.finish_request事件,把當前請求從請求棧中彈出,當前請求就完成。69         return $this->filterResponse($response, $request, $type);70 71         // 千萬別忘記了,filterResponse執(zhí)行完后,Symfony2內(nèi)核事件處理流程還有最后一步,位于app_dev.php[app.php]最后一行,72         // $kernel->terminate($request, $response);這個方法觸發(fā)kernel.terminate事件,此時,Symfony2已經(jīng)響應(yīng)了客戶端的請求,73         // 向客戶端輸出了Response對象。監(jiān)聽kernel.terminate事件的監(jiān)聽器,主要是為了完成一些耗時的操作,操作的結(jié)果不需要返回給74         // 客戶端的,例如郵件發(fā)送、圖片壓縮等等。75         // 到這里,Symfony2的整個流程就走完了。76     }
HttpKernel::filterResponse方法和HttpKernel::finishRequest方法:
 1     private function filterResponse(Response $response, Request $request, $type) 2     { 3         $event = new FilterResponseEvent($this, $request, $type,
發(fā)表評論 共有條評論
用戶名: 密碼:
驗證碼: 匿名發(fā)表
主站蜘蛛池模板: 南岸区| 金川县| 三门峡市| 泗水县| 阜南县| 沙坪坝区| 奉新县| 嘉禾县| 特克斯县| 嘉义县| 黄石市| 米易县| 新晃| 开原市| 青川县| 大余县| 长春市| 达尔| 永兴县| 辽阳县| 饶阳县| 都匀市| 桦川县| 威宁| 亚东县| 鹤庆县| 德钦县| 治多县| 赤壁市| 水城县| 曲靖市| 泸西县| 柳江县| 眉山市| 东平县| 新乐市| 嘉兴市| 湾仔区| 漠河县| 江永县| 天柱县|