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

                合規國際互聯網加速 OSASE為企業客戶提供高速穩定SD-WAN國際加速解決方案。 廣告
                # 調度控制器(Dispatching Controllers) [Phalcon\\Mvc\\Dispatcher](http://docs.iphalcon.cn/api/Phalcon_Mvc_Dispatcher.html)是MVC應用中負責實例化 控制器和執行在這些控制器上必要動作的組件。理解它的操作和能力將能幫助我們獲得更多Phalcon框架提供的服務。 ## 循環調度(The Dispatch Loop) 在MVC流中,這是一個重要的處理環節,特別對于控制器這部分。這些處理 發生在控制調度器中。控制器的文件將會被依次讀取、加載和實例化。然后指定的action將會被執行。 如果一個動作將這個流轉發給了另一個控制器/動作,控制調度器將會再次啟動。為了更好 解釋這一點,以下示例怡到好處地說明了在[Phalcon\\Mvc\\Dispatcher](http://docs.iphalcon.cn/api/Phalcon_Mvc_Dispatcher.html)中的處理過程: ~~~ <?php // 循環調度 while (!$finished) { $finished = true; $controllerClass = $controllerName . "Controller"; // 通過自動加載器實例化控制器類 $controller = new $controllerClass(); // 執行action call_user_func_array( [ $controller, $actionName . "Action" ], $params ); // $finished應該重新加載以檢測MVC流 // 是否轉發給了另一個控制器 $finished = true; } ~~~ 上面的代碼缺少了驗證,過濾器和額外的檢查,但它演示了在調度器中正常的操作流。 ### 循環調度事件(Dispatch Loop Events) [Phalcon\\Mvc\\Dispatcher](http://docs.iphalcon.cn/api/Phalcon_Mvc_Dispatcher.html)可以發送事件給當前的[EventsManager](http://docs.iphalcon.cn/reference/events.html)。 事件會以“dispatch”類型被所觸發。當返回false時有些事件可以終止當前激活的操作。已支持的事件如下: [INVO](http://docs.iphalcon.cn/reference/tutorial-invo.html)這篇導讀說明了如何從通過結合[Acl](http://docs.iphalcon.cn/reference/acl.html)實現的一個安全過濾器中獲得事件調度的好處。 以下例子演示了如何將偵聽者綁定到組件上: ~~~ <?php use Phalcon\Mvc\Dispatcher as MvcDispatcher; use Phalcon\Events\Event; use Phalcon\Events\Manager as EventsManager; $di->set( "dispatcher", function () { // 創建一個事件管理 $eventsManager = new EventsManager(); // 為“dispatch”類型附上一個偵聽者 $eventsManager->attach( "dispatch", function (Event $event, $dispatcher) { // ... } ); $dispatcher = new MvcDispatcher(); // 將$eventsManager綁定到視圖組件 $dispatcher->setEventsManager($eventsManager); return $dispatcher; }, true ); ~~~ 一個實例化的控制器會自動作為事件調度的偵聽者,所以你可以實現回調函數: ~~~ <?php use Phalcon\Mvc\Controller; use Phalcon\Mvc\Dispatcher; class PostsController extends Controller { public function beforeExecuteRoute(Dispatcher $dispatcher) { // 在每一個找到的動作前執行 } public function afterExecuteRoute(Dispatcher $dispatcher) { // 在每一個找到的動作后執行 } } ~~~ 注解 Methods on event listeners accept an[Phalcon\\Events\\Event](http://docs.iphalcon.cn/api/Phalcon_Events_Event.html)object as their first parameter - methods in controllers do not. ## 轉發到其他動作(Forwarding to other actions) 循環調度允許我們轉發執行流到另一個控制器/動作。這對于檢查用戶是否可以 訪問頁面,將用戶重定向到其他屏幕或簡單地代碼重用都非常有用。 ~~~ <?php use Phalcon\Mvc\Controller; class PostsController extends Controller { public function indexAction() { } public function saveAction($year, $postTitle) { // ... 儲存一些產品并且轉發用戶 // 將流轉發到index動作 $this->dispatcher->forward( [ "controller" => "posts", "action" => "index", ] ); } } ~~~ 請注意制造一個“forward”并不等同于制造一個HTTP的重定向。盡管這兩者表面上最終效果都一樣。 “forward”不會重新加載當前頁面,全部的重定向都只發生在一個請求里面,而HTTP重定向則需要兩次請求 才能完成這個流程。 更多轉發示例: ~~~ <?php // 將流轉發到當前控制器的另一個動作 $this->dispatcher->forward( [ "action" => "search" ] ); // 將流轉發到當前控制器的另一個動作 // 傳遞參數 $this->dispatcher->forward( [ "action" => "search", "params" => [1, 2, 3] ] ); ~~~ 一個轉發的動作可以接受以下參數: | 參數 | 觸發 | | --- | --- | | controller | 一個待轉發且有效的控制器名字。 | | action | 一個待轉發且有效的動作名字。 | | params | 一個傳遞給動作的數組參數。 | | namespace | 一個控制器對應的命名空間名字。 | ## 準備參數(Preparing Parameters) 多得[Phalcon\\Mvc\\Dispatcher](http://docs.iphalcon.cn/api/Phalcon_Mvc_Dispatcher.html)提供的鉤子函數, 你可以簡單地 調整你的應用來匹配URL格式: 例如,你想把你的URL看起來像這樣:[http://example.com/controller/key1/value1/key2/value](http://example.com/controller/key1/value1/key2/value) 默認下,參數會按URL傳遞的順序傳給對應的動作,你可以按期望來轉換他們: ~~~ <?php use Phalcon\Dispatcher; use Phalcon\Mvc\Dispatcher as MvcDispatcher; use Phalcon\Events\Event; use Phalcon\Events\Manager as EventsManager; $di->set( "dispatcher", function () { // 創建一個事件管理 $eventsManager = new EventsManager(); // 附上一個偵聽者 $eventsManager->attach( "dispatch:beforeDispatchLoop", function (Event $event, $dispatcher) { $params = $dispatcher->getParams(); $keyParams = []; // 用奇數參數作key,用偶數作值 foreach ($params as $i => $value) { if ($i & 1) { // Previous param $key = $params[$i - 1]; $keyParams[$key] = $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; use Phalcon\Mvc\Dispatcher as MvcDispatcher; use Phalcon\Events\Event; use Phalcon\Events\Manager as EventsManager; $di->set( "dispatcher", function () { // 創建一個事件管理 $eventsManager = new EventsManager(); // 附上一個偵聽者 $eventsManager->attach( "dispatch:beforeDispatchLoop", function (Event $event, $dispatcher) { $params = $dispatcher->getParams(); $keyParams = []; // 將每一個參數分解成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](http://docs.iphalcon.cn/api/Phalcon_Di_Injectable.html)的組件中獲得這些參數。 ~~~ <?php use Phalcon\Mvc\Controller; class PostsController extends 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; use Phalcon\Mvc\Dispatcher as MvcDispatcher; use Phalcon\Events\Event; use Phalcon\Events\Manager as EventsManager; $di->set( "dispatcher", function () { // 創建一個事件管理 $eventsManager = new EventsManager(); // Camelize動作 $eventsManager->attach( "dispatch:beforeDispatchLoop", function (Event $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; use Phalcon\Events\Event; use Phalcon\Events\Manager as EventsManager; $di->set( "dispatcher", function () { // 創建一個事件管理 $eventsManager = new EventsManager(); // 在調度前刪除擴展 $eventsManager->attach( "dispatch:beforeDispatchLoop", function (Event $event, $dispatcher) { $action = $dispatcher->getActionName(); // 刪除擴展 $action = preg_replace("/\.php$/", "", $action); // 重寫動作 $dispatcher->setActionName($action); } ); $dispatcher = new MvcDispatcher(); $dispatcher->setEventsManager($eventsManager); return $dispatcher; } ); ~~~ ### 注入模型實例(Inject model instances) 在這個實例中,開發人員想要觀察動作接收到的參數以便可以動態注入模型實例。 控制器看起來像這樣: ~~~ <?php use Phalcon\Mvc\Controller; class PostsController extends Controller { /** * 顯示$post * * @param \Posts $post */ public function showAction(Posts $post) { $this->view->post = $post; } } ~~~ ‘showAction’方法接收到一個 Posts 模型的實例,開發人員可以 在調度動作和準備映射參數前進行觀察: ~~~ <?php use Exception; use Phalcon\Mvc\Model; use Phalcon\Mvc\Dispatcher as MvcDispatcher; use Phalcon\Events\Event; use Phalcon\Events\Manager as EventsManager; use ReflectionMethod; $di->set( "dispatcher", function () { // 創建一個事件管理 $eventsManager = new EventsManager(); $eventsManager->attach( "dispatch:beforeDispatchLoop", function (Event $event, $dispatcher) { // 可能的控制器類名 $controllerName = $dispatcher->getControllerClass(); // 可能的方法名 $actionName = $dispatcher->getActiveMethod(); try { // 從反射中獲取將要被執行的方法 $reflection = new ReflectionMethod($controllerName, $actionName); $parameters = $reflection->getParameters(); // 參數檢查 foreach ($parameters as $parameter) { // 獲取期望的模型名字 $className = $parameter->getClass()->name; // 檢查參數是否為模型的實例 if (is_subclass_of($className, Model::class)) { $model = $className::findFirstById($dispatcher->getParams()[0]); // 根據模型實例重寫參數 $dispatcher->setParams([$model]); } } } catch (Exception $e) { // 異常觸發,類或者動作不存在? } } ); $dispatcher = new MvcDispatcher(); $dispatcher->setEventsManager($eventsManager); return $dispatcher; } ); ~~~ 上面示例出于學術目的已經作了簡化。 開發人員可以在執行動作前注入任何類型的依賴或者模型,以進行提高和強化。 From 3.1.x onwards the dispatcher also comes with an option to handle this internally for all models passed into a controller action by using[Phalcon\\Mvc\\Model\\Binder](http://docs.iphalcon.cn/api/Phalcon_Mvc_Model_Binder.html). ~~~ use Phalcon\Mvc\Dispatcher; use Phalcon\Mvc\Model\Binder; $dispatcher = new Dispatcher(); $dispatcher->setModelBinder(new Binder()); return $dispatcher; ~~~ > Since Binder object is using internally Reflection Api which can be heavy there is ability to set cache. This can be done by using second argument in`setModelBinder()`which can also accept service name or just by passing cache instance to`Binder`constructor. It also introduces a new interface[Phalcon\\Mvc\\Model\\Binder\\BindableInterface](http://docs.iphalcon.cn/api/Phalcon_Mvc_Model_Binder_BindableInterface.html)which allows you to define the controllers associated models to allow models binding in base controllers. For example, you have a base CrudController which your PostsController extends from. Your CrudController looks something like this: ~~~ use Phalcon\Mvc\Controller; use Phalcon\Mvc\Model; class CrudController extends Controller { /** * Show action * * @param Model $model */ public function showAction(Model $model) { $this->view->model = $model; } } ~~~ In your PostsController you need to define which model the controller is associated with. This is done by implementing the[Phalcon\\Mvc\\Model\\Binder\\BindableInterface](http://docs.iphalcon.cn/api/Phalcon_Mvc_Model_Binder_BindableInterface.html)which will add the`getModelName()`method from which you can return the model name. It can return string with just one model name or associative array where key is parameter name. ~~~ use Phalcon\Mvc\Model\Binder\BindableInterface; use Models\Posts; class PostsController extends CrudController implements BindableInterface { public static function getModelName() { return Posts::class; } } ~~~ By declaring the model associated with the PostsController the binder can check the controller for the`getModelName()`method before passing the defined model into the parent show action. If your project structure does not use any parent controller you can of course still bind the model directly into the controller action: ~~~ use Phalcon\Mvc\Controller; use Models\Posts; class PostsController extends Controller { /** * Shows posts * * @param Posts $post */ public function showAction(Posts $post) { $this->view->post = $post; } } ~~~ > Currently the binder will only use the models primary key to perform a`findFirst()`on. An example route for the above would be /posts/show/{1} ## 處理 Not-Found 錯誤(Handling Not-Found Exceptions) 使用[EventsManager](http://docs.iphalcon.cn/reference/events.html),可以在調度器找不到對應的控制器/動作組時而拋出異常前,插入一個鉤子: ~~~ <?php use Exception; use Phalcon\Dispatcher; use Phalcon\Mvc\Dispatcher as MvcDispatcher; use Phalcon\Events\Event; use Phalcon\Events\Manager as EventsManager; use Phalcon\Mvc\Dispatcher\Exception as DispatchException; $di->setShared( "dispatcher", function () { // 創建一個事件管理 $eventsManager = new EventsManager(); // 附上一個偵聽者 $eventsManager->attach( "dispatch:beforeException", function (Event $event, $dispatcher, Exception $exception) { // 處理404異常 if ($exception instanceof DispatchException) { $dispatcher->forward( [ "controller" => "index", "action" => "show404", ] ); return false; } // 代替控制器或者動作不存在時的路徑 switch ($exception->getCode()) { case Dispatcher::EXCEPTION_HANDLER_NOT_FOUND: case Dispatcher::EXCEPTION_ACTION_NOT_FOUND: $dispatcher->forward( [ "controller" => "index", "action" => "show404", ] ); return false; } } ); $dispatcher = new MvcDispatcher(); // 將EventsManager綁定到調度器 $dispatcher->setEventsManager($eventsManager); return $dispatcher; } ); ~~~ 當然,這個方法也可以移至獨立的插件類中,使得在循環調度產生異常時可以有超過一個類執行需要的動作: ~~~ <?php use Exception; use Phalcon\Events\Event; use Phalcon\Mvc\Dispatcher; use Phalcon\Mvc\Dispatcher\Exception as DispatchException; class ExceptionsPlugin { public function beforeException(Event $event, Dispatcher $dispatcher, Exception $exception) { // Default error action $action = "show503"; // 處理404異常 if ($exception instanceof DispatchException) { $action = "show404"; } $dispatcher->forward( [ "controller" => "index", "action" => $action, ] ); return false; } } ~~~ > 僅僅當異常產生于調度器或者異常產生于被執行的動作時才會通知’beforeException’里面的事件。 偵聽者或者控制器事件中產生的異常則會重定向到最近的try/catch。 ## 自定義調度器(Implementing your own Dispatcher) 為了創建自定義調度器,必須實現[Phalcon\\Mvc\\DispatcherInterface](http://docs.iphalcon.cn/api/Phalcon_Mvc_DispatcherInterface.html)接口, 從而替換Phalcon框架默認提供的調度器。
                  <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>

                              哎呀哎呀视频在线观看