<ruby id="bdb3f"></ruby>

    <p id="bdb3f"><cite id="bdb3f"></cite></p>

      <p id="bdb3f"><cite id="bdb3f"><th id="bdb3f"></th></cite></p><p id="bdb3f"></p>
        <p id="bdb3f"><cite id="bdb3f"></cite></p>

          <pre id="bdb3f"></pre>
          <pre id="bdb3f"><del id="bdb3f"><thead id="bdb3f"></thead></del></pre>

          <ruby id="bdb3f"><mark id="bdb3f"></mark></ruby><ruby id="bdb3f"></ruby>
          <pre id="bdb3f"><pre id="bdb3f"><mark id="bdb3f"></mark></pre></pre><output id="bdb3f"></output><p id="bdb3f"></p><p id="bdb3f"></p>

          <pre id="bdb3f"><del id="bdb3f"><progress id="bdb3f"></progress></del></pre>

                <ruby id="bdb3f"></ruby>

                ThinkChat2.0新版上線,更智能更精彩,支持會話、畫圖、視頻、閱讀、搜索等,送10W Token,即刻開啟你的AI之旅 廣告
                # 調度控制器(Dispatching Controllers)[](# "永久鏈接至標題") [*Phalcon\Mvc\Dispatcher*](#) 是MVC應用中負責實例化控制器和執行在這些控制器上必要動作的組件。理解它的操作和能力將能幫助我們獲得更多Phalcon框架提供的服務。 ### 循環調度(The Dispatch Loop)[](# "永久鏈接至標題") 在MVC流中,這是一個重要的處理環節,特別對于控制器這部分。這些處理發生在控制調度器中。控制器的文件將會被依次讀取、加載和實例化。然后指定的action將會被執行。如果一個動作將這個流轉發給了另一個控制器/動作,控制調度器將會再次啟動。為了更好解釋這一點,以下示例怡到好處地說明了在 [*Phalcon\Mvc\Dispatcher*](#) 中的處理過程: ~~~ <?php // 循環調度 while (!$finished) { $finished = true; $controllerClass = $controllerName . "Controller"; // 通過自動加載器實例化控制器類 $controller = new $controllerClass(); // 執行action call_user_func_array(array($controller, $actionName . "Action"), $params); // $finished應該重新加載以檢測MVC流 // 是否轉發給了另一個控制器 $finished = true; } ~~~ 上面的代碼缺少了驗證,過濾器和額外的檢查,但它演示了在調度器中正常的操作流。 ### 循環調度事件(Dispatch Loop Events)[](# "永久鏈接至標題") [*Phalcon\Mvc\Dispatcher*](#) 可以發送事件給當前的 [*EventsManager*](#) 。事件會以“dispatch”類型被所觸發。當返回false時有些事件可以終止當前激活的操作。已支持的事件如下: | 事件名稱 | 何時觸發 | 此操作是否可終止? | 觸發于 | |-----|-----|-----|-----| | beforeDispatchLoop | 在進入循環調度前觸發。此時,調度器不知道將要執行的控制器或者動作是否存在。調度器只知道路由傳遞過來的信息。 | 是 | 偵聽者 | | beforeDispatch | 在進入循環調度后觸發。此時,調度器不知道將要執行的控制器或者動作是否存在。調度器只知道路由傳遞過來的信息。 | 是 | 偵聽者 | | beforeExecuteRoute | 在執行控制器/動作方法前觸發。此時,調度器已經初始化了控制器并知道動作是否存在。 | 是 | 偵聽者/控制器 | | initialize | 允許在請求中全局初始化控制器。 | 否 | 控制器 | | afterExecuteRoute | 在執行控制器/動作方法后觸發。由于此操作不可終止,所以僅在執行動作后才使用此事件進行清理工作。 | 否 | 偵聽者/控制器 | | beforeNotFoundAction | 當控制器中的動作找不到時觸發。 | 是 | 偵聽者 | | beforeException | 在調度器拋出任意異常前觸發。 | 是 | 偵聽者 | | afterDispatch | 在執行控制器/動作方法后觸發。由于此操作不可終止,所以僅在執行動作后才使用此事件進行清理工作。 | 是 | 偵聽者 | | afterDispatchLoop | 在退出循環調度后觸發。 | 否 | 偵聽者 | [*INVO*](#) 這篇導讀說明了如何從通過結合 [*Acl*](#) 實現的一個安全過濾器中獲得事件調度的好處。 以下例子演示了如何將偵聽者綁定到組件上: ~~~ <?php use Phalcon\Mvc\Dispatcher as MvcDispatcher, Phalcon\Events\Manager as EventsManager; $di->set('dispatcher', function () { // 創建一個事件管理 $eventsManager = new EventsManager(); // 為“dispatch”類型附上一個偵聽者 $eventsManager->attach("dispatch", function ($event, $dispatcher) { // ... }); $dispatcher = new MvcDispatcher(); // 將$eventsManager綁定到視圖組件 $dispatcher->setEventsManager($eventsManager); return $dispatcher; }, true); ~~~ 一個實例化的控制器會自動作為事件調度的偵聽者,所以你可以實現回調函數: ~~~ <?php class PostsController extends \Phalcon\Mvc\Controller { public function beforeExecuteRoute($dispatcher) { // 在每一個找到的動作前執行 } public function afterExecuteRoute($dispatcher) { // 在每一個找到的動作后執行 } } ~~~ ### 轉發到其他動作(Forwarding to other actions)[](# "永久鏈接至標題") 循環調度允許我們轉發執行流到另一個控制器/動作。這對于檢查用戶是否可以訪問頁面,將用戶重定向到其他屏幕或簡單地代碼重用都非常有用。 ~~~ <?php class PostsController extends \Phalcon\Mvc\Controller { public function indexAction() { } public function saveAction($year, $postTitle) { // .. 儲存一些產品并且轉發用戶 // 將流轉發到index動作 $this->dispatcher->forward(array( "controller" => "post", "action" => "index" )); } } ~~~ 請注意制造一個“forward”并不等同于制造一個HTTP的重定向。盡管這兩者表面上最終效果都一樣。“forward”不會重新加載當前頁面,全部的重定向都只發生在一個請求里面,而HTTP重定向則需要兩次請求才能完成這個流程。 更多轉發示例: ~~~ <?php // 將流轉發到當前控制器的另一個動作 $this->dispatcher->forward(array( "action" => "search" )); // 將流轉發到當前控制器的另一個動作 // 傳遞參數 $this->dispatcher->forward(array( "action" => "search", "params" => array(1, 2, 3) )); ~~~ 一個轉發的動作可以接受以下參數: | 參數 | 觸發 | |-----|-----| | controller | 一個待轉發且有效的控制器名字。 | | action | 一個待轉發且有效的動作名字。 | | params | 一個傳遞給動作的數組參數。 | | namespace | 一個控制器對應的命名空間名字。 | ### 準備參數(Preparing Parameters)[](# "永久鏈接至標題") 多得 [*Phalcon\Mvc\Dispatcher*](#) 提供的鉤子函數, 你可以簡單地調整你的應用來匹配URL格式: 例如,你想把你的URL看起來像這樣:[http://example.com/controller/key1/value1/key2/value](http://example.com/controller/key1/value1/key2/value) 默認下,參數會按URL傳遞的順序傳給對應的動作,你可以按期望來轉換他們: ~~~ <?php use Phalcon\Dispatcher, Phalcon\Mvc\Dispatcher as MvcDispatcher, Phalcon\Events\Manager as EventsManager; $di->set('dispatcher', function () { // 創建一個事件管理 $eventsManager = new EventsManager(); // 附上一個偵聽者 $eventsManager->attach("dispatch:beforeDispatchLoop", function ($event, $dispatcher) { $keyParams = array(); $params = $dispatcher->getParams(); // 用奇數參數作key,用偶數作值 foreach ($params as $number => $value) { if ($number & 1) { $keyParams[$params[$number - 1]] = $value; } } // 重寫參數 $dispatcher->setParams($keyParams); }); $dispatcher = new MvcDispatcher(); $dispatcher->setEventsManager($eventsManager); return $dispatcher; }); ~~~ 如果期望的鏈接是這樣: [http://example.com/controller/key1:value1/key2:value](http://example.com/controller/key1:value1/key2:value),那么就需要以下這樣的代碼: ~~~ <?php use Phalcon\Dispatcher, Phalcon\Mvc\Dispatcher as MvcDispatcher, Phalcon\Events\Manager as EventsManager; $di->set('dispatcher', function () { // 創建一個事件管理 $eventsManager = new EventsManager(); // 附上一個偵聽者 $eventsManager->attach("dispatch:beforeDispatchLoop", function ($event, $dispatcher) { $keyParams = array(); $params = $dispatcher->getParams(); // 將每一個參數分解成key、值 對 foreach ($params as $number => $value) { $parts = explode(':', $value); $keyParams[$parts[0]] = $parts[1]; } // 重寫參數 $dispatcher->setParams($keyParams); }); $dispatcher = new MvcDispatcher(); $dispatcher->setEventsManager($eventsManager); return $dispatcher; }); ~~~ ### 獲取參數(Getting Parameters)[](# "永久鏈接至標題") 當路由提供了命名的參數變量,你就可以在控制器、視圖或者任何一個繼承了[*Phalcon\DI\Injectable*](#) 的組件中獲得這些參數。 ~~~ <?php class PostsController extends \Phalcon\Mvc\Controller { public function indexAction() { } public function saveAction() { // 從URL傳遞過來的參數中獲取title // 或者在一個事件中準備 $title = $this->dispatcher->getParam("title"); // 從URL傳遞過來的參數中獲取year // 或者在一個事件中準備并且進行過濾 $year = $this->dispatcher->getParam("year", "int"); } } ~~~ ### 準備行動(Preparing actions)[](# "永久鏈接至標題") 你也可以為動作定義一個調度前的映射表。 ### 轉換動作名(Camelize action names)[](# "永久鏈接至標題") 如果原始鏈接是:[http://example.com/admin/products/show-latest-products](http://example.com/admin/products/show-latest-products),例如你想把'show-latest-products'轉換成'ShowLatestProducts',需要以下代碼: ~~~ <?php use Phalcon\Text, Phalcon\Mvc\Dispatcher as MvcDispatcher, Phalcon\Events\Manager as EventsManager; $di->set('dispatcher', function () { // 創建一個事件管理 $eventsManager = new EventsManager(); // Camelize動作 $eventsManager->attach("dispatch:beforeDispatchLoop", function ($event, $dispatcher) { $dispatcher->setActionName(Text::camelize($dispatcher->getActionName())); }); $dispatcher = new MvcDispatcher(); $dispatcher->setEventsManager($eventsManager); return $dispatcher; }); ~~~ ### 刪除遺留的擴展名(Remove legacy extensions)[](# "永久鏈接至標題") 如果原始鏈接總是包含一個'.php'擴展名: [http://example.com/admin/products/show-latest-products.php](http://example.com/admin/products/show-latest-products.php)[http://example.com/admin/products/index.php](http://example.com/admin/products/index.php) 你可以在調度對應的控制器/動作組前將它刪除: ~~~ <?php use Phalcon\Mvc\Dispatcher as MvcDispatcher, Phalcon\Events\Manager as EventsManager; $di->set('dispatcher', function () { // 創建一個事件管理 $eventsManager = new EventsManager(); // 在調度前刪除擴展 $eventsManager->attach("dispatch:beforeDispatchLoop", function ($event, $dispatcher) { // 刪除擴展 $action = preg_replace('/\.php$/', '', $dispatcher->getActionName()); // 重寫動作 $dispatcher->setActionName($action); }); $dispatcher = new MvcDispatcher(); $dispatcher->setEventsManager($eventsManager); return $dispatcher; }); ~~~ ### 注入模型實例(Inject model instances)[](# "永久鏈接至標題") 在這個實例中,開發人員想要觀察動作接收到的參數以便可以動態注入模型實例。 控制器看起來像這樣: ~~~ <?php class PostsController extends \Phalcon\Mvc\Controller { /** * 顯示$post * * @param \Posts $post */ public function showAction(Posts $post) { $this->view->post = $post; } } ~~~ ‘showAction'方法接收到一個 Posts 模型的實例,開發人員可以在調度動作和準備映射參數前進行觀察: ~~~ <?php use Phalcon\Text, Phalcon\Mvc\Dispatcher as MvcDispatcher, Phalcon\Events\Manager as EventsManager; $di->set('dispatcher', function () { // 創建一個事件管理 $eventsManager = new EventsManager(); $eventsManager->attach("dispatch:beforeDispatchLoop", function ($event, $dispatcher) { // 可能的控制器類名 $controllerName = Text::camelize($dispatcher->getControllerName()) . 'Controller'; // 可能的方法名 $actionName = $dispatcher->getActionName() . 'Action'; try { // 從反射中獲取將要被執行的方法 $reflection = new \ReflectionMethod($controllerName, $actionName); // 參數檢查 foreach ($reflection->getParameters() as $parameter) { // 獲取期望的模型名字 $className = $parameter->getClass()->name; // 檢查參數是否為模型的實例 if (is_subclass_of($className, 'Phalcon\Mvc\Model')) { $model = $className::findFirstById($dispatcher->getParams()[0]); // 根據模型實例重寫參數 $dispatcher->setParams(array($model)); } } } catch (\Exception $e) { // 異常觸發,類或者動作不存在? } }); $dispatcher = new MvcDispatcher(); $dispatcher->setEventsManager($eventsManager); return $dispatcher; }); ~~~ 上面示例出于學術目的已經作了簡化。開發人員可以在執行動作前注入任何類型的依賴或者模型,以進行提高和強化。 ### 處理 Not-Found 錯誤(Handling Not-Found Exceptions)[](# "永久鏈接至標題") 使用 [*EventsManager*](#) ,可以在調度器找不到對應的控制器/動作組時而拋出異常前,插入一個鉤子: ~~~ <?php use Phalcon\Dispatcher, Phalcon\Mvc\Dispatcher as MvcDispatcher, Phalcon\Events\Manager as EventsManager, Phalcon\Mvc\Dispatcher\Exception as DispatchException; $di->set('dispatcher', function () { // 創建一個事件管理 $eventsManager = new EventsManager(); // 附上一個偵聽者 $eventsManager->attach("dispatch:beforeException", function ($event, $dispatcher, $exception) { // 處理404異常 if ($exception instanceof DispatchException) { $dispatcher->forward(array( 'controller' => 'index', 'action' => 'show404' )); return false; } // 代替控制器或者動作不存在時的路徑 if ($event->getType() == 'beforeException') { switch ($exception->getCode()) { case \Phalcon\Dispatcher::EXCEPTION_HANDLER_NOT_FOUND: case \Phalcon\Dispatcher::EXCEPTION_ACTION_NOT_FOUND: $dispatcher->forward(array( 'controller' => 'index', 'action' => 'show404' )); return false; } } }); $dispatcher = new \Phalcon\Mvc\Dispatcher(); // 將EventsManager綁定到調度器 $dispatcher->setEventsManager($eventsManager); return $dispatcher; }, true); ~~~ 當然,這個方法也可以移至獨立的插件類中,使得在循環調度產生異常時可以有超過一個類執行需要的動作: ~~~ <?php use Phalcon\Mvc\Dispatcher, Phalcon\Events\Event, Phalcon\Mvc\Dispatcher\Exception as DispatchException; class ExceptionsPlugin { public function beforeException(Event $event, Dispatcher $dispatcher, $exception) { // 處理404異常 if ($exception instanceof DispatchException) { $dispatcher->forward(array( 'controller' => 'index', 'action' => 'show404' )); return false; } // 處理其他異常 $dispatcher->forward(array( 'controller' => 'index', 'action' => 'show503' )); return false; } } ~~~ > 僅僅當異常產生于調度器或者異常產生于被執行的動作時才會通知'beforeException'里面的事件。偵聽者或者控制器事件中產生的異常則會重定向到最近的try/catch。 ### 自定義調度器(Implementing your own Dispatcher)[](# "永久鏈接至標題") 為了創建自定義調度器,必須實現 [*Phalcon\Mvc\DispatcherInterface*](#) 接口,從而替換Phalcon框架默認提供的調度器。 | - [索引](# "總目錄") - [下一頁](# "微應用(Micro Applications)") | - [上一頁](# "路由(Routing)") |
                  <ruby id="bdb3f"></ruby>

                  <p id="bdb3f"><cite id="bdb3f"></cite></p>

                    <p id="bdb3f"><cite id="bdb3f"><th id="bdb3f"></th></cite></p><p id="bdb3f"></p>
                      <p id="bdb3f"><cite id="bdb3f"></cite></p>

                        <pre id="bdb3f"></pre>
                        <pre id="bdb3f"><del id="bdb3f"><thead id="bdb3f"></thead></del></pre>

                        <ruby id="bdb3f"><mark id="bdb3f"></mark></ruby><ruby id="bdb3f"></ruby>
                        <pre id="bdb3f"><pre id="bdb3f"><mark id="bdb3f"></mark></pre></pre><output id="bdb3f"></output><p id="bdb3f"></p><p id="bdb3f"></p>

                        <pre id="bdb3f"><del id="bdb3f"><progress id="bdb3f"></progress></del></pre>

                              <ruby id="bdb3f"></ruby>

                              哎呀哎呀视频在线观看