<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>

                ??一站式輕松地調用各大LLM模型接口,支持GPT4、智譜、豆包、星火、月之暗面及文生圖、文生視頻 廣告
                # 調度控制器(Dispatching Controllers) # 調度控制器(Dispatching Controllers) [*Phalcon\\Mvc\\Dispatcher*](#) 是MVC應用中負責實例化控制器和執行在這些控制器上必要動作的組件。理解它的操作和能力將能幫助我們獲得更多Phalcon框架提供的服務。 ### 循環調度(The Dispatch Loop) 在MVC流中,這是一個重要的處理環節,特別對于控制器這部分。這些處理發生在控制調度器中。控制器的文件將會被依次讀取、加載和實例化。然后指定的action將會被執行。如果一個動作將這個流轉發給了另一個控制器/動作,控制調度器將會再次啟動。為了更好解釋這一點,以下示例怡到好處地說明了在 [*Phalcon\\Mvc\\Dispatcher*](#) 中的處理過程: ``` <pre class="calibre14">``` <?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*](#) 實現的一個安全過濾器中獲得事件調度的好處。 以下例子演示了如何將偵聽者綁定到組件上: ``` <pre class="calibre14">``` <?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); ``` ``` 一個實例化的控制器會自動作為事件調度的偵聽者,所以你可以實現回調函數: ``` <pre class="calibre14">``` <?php class PostsController extends \Phalcon\Mvc\Controller { public function beforeExecuteRoute($dispatcher) { // 在每一個找到的動作前執行 } public function afterExecuteRoute($dispatcher) { // 在每一個找到的動作后執行 } } ``` ``` ### 轉發到其他動作(Forwarding to other actions) 循環調度允許我們轉發執行流到另一個控制器/動作。這對于檢查用戶是否可以訪問頁面,將用戶重定向到其他屏幕或簡單地代碼重用都非常有用。 ``` <pre class="calibre14">``` <?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重定向則需要兩次請求才能完成這個流程。 更多轉發示例: ``` <pre class="calibre14">``` <?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> 默認下,參數會按URL傳遞的順序傳給對應的動作,你可以按期望來轉換他們: ``` <pre class="calibre14">``` <?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>,那么就需要以下這樣的代碼: ``` <pre class="calibre14">``` <?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*](#) 的組件中獲得這些參數。 ``` <pre class="calibre14">``` <?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>,例如你想把'show-latest-products'轉換成'ShowLatestProducts',需要以下代碼: ``` <pre class="calibre14">``` <?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/index.php> 你可以在調度對應的控制器/動作組前將它刪除: ``` <pre class="calibre14">``` <?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) 在這個實例中,開發人員想要觀察動作接收到的參數以便可以動態注入模型實例。 控制器看起來像這樣: ``` <pre class="calibre14">``` <?php class PostsController extends \Phalcon\Mvc\Controller { /** * 顯示$post * * @param \Posts $post */ public function showAction(Posts $post) { $this->view->post = $post; } } ``` ``` ‘showAction'方法接收到一個 Posts 模型的實例,開發人員可以在調度動作和準備映射參數前進行觀察: ``` <pre class="calibre14">``` <?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*](#) ,可以在調度器找不到對應的控制器/動作組時而拋出異常前,插入一個鉤子: ``` <pre class="calibre14">``` <?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); ``` ``` 當然,這個方法也可以移至獨立的插件類中,使得在循環調度產生異常時可以有超過一個類執行需要的動作: ``` <pre class="calibre14">``` <?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>

                              哎呀哎呀视频在线观看