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

                企業??AI智能體構建引擎,智能編排和調試,一鍵部署,支持知識庫和私有化部署方案 廣告
                [TOC] # 調度控制器 `Phalcon\Mvc\Dispatcher` 是負責實例化控制器并在MVC應用程序中對它們執行所需操作的組件。了解其操作和功能有助于我們從框架提供的服務中獲得更多。 ## 調度循環 這是一個重要的過程,與MVC流本身有很大關系,特別是與控制器部分有關。工作發生在控制器調度程序中。讀取,加載和實例化控制器文件。然后執行所需的操作。如果操作將流轉發到另一個控制器/操作,則控制器調度程序再次啟動。為了更好地說明這一點,以下示例顯示了`Phalcon\Mvc\Dispatcher`中執行的大致過程: ```php <?php // Dispatch loop while (!$finished) { $finished = true; $controllerClass = $controllerName . 'Controller'; // Instantiating the controller class via autoloaders $controller = new $controllerClass(); // Execute the action call_user_func_array( [ $controller, $actionName . 'Action' ], $params ); // '$finished' should be reloaded to check if the flow was forwarded to another controller $finished = true; } ``` 上面的代碼缺少驗證,過濾器和其他檢查,但它演示了調度程序中的正常操作流程。 ### 分發循環事件 `Phalcon\Mvc\Dispatcher` 能夠將事件發送到EventsManager(如果存在)。使用類型`dispatch`觸發事件。返回布爾值`false`時的某些事件可能會停止活動操作。支持以下事件: | 事件名稱 | 觸發 | Can stop operation? | Triggered on | | -------------------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ------------------- | --------------------- | | beforeDispatchLoop | 在進入調度循環之前觸發。此時,`Dispatcher`不知道控制器或要執行的動作是否存在。`Dispatcher`只知道路由器傳遞的信息。 | Yes | Listeners | | beforeDispatch | 進入調度循環后觸發。此時,`Dispatcher`不知道控制器或要執行的動作是否存在。`Dispatcher`只知道路由器傳遞的信息 | Yes | Listeners | | beforeExecuteRoute | 在執行控制器/操作方法之前觸發。此時,調度程序已初始化控制器并知道操作是否存在。 | Yes | Listeners/Controllers | | initialize | 在執行控制器/操作方法之前觸發。此時,調度程序已初始化控制器并知道操作是否存在。 | No | Controllers | | afterExecuteRoute | 執行控制器/操作方法后觸發。由于無法停止操作,因此僅在執行操作后使用此事件進行清理 | No | Listeners/Controllers | | beforeNotFoundAction |在控制器中找不到操作時觸發 | Yes | Listeners | | beforeException | 在調度程序拋出任何異常之前觸發 | Yes | Listeners | | afterDispatch |執行控制器/操作方法后觸發。由于無法停止操作,因此僅在執行操作后使用此事件進行清理 | Yes | Listeners | | afterDispatchLoop | 退出調度循環后觸發 | No | Listeners | | afterBinding | 模型綁定后但在執行路徑之前觸發 | Yes | Listeners/Controllers | `INVO`教程展示了如何利用使用`Acl`實現安全過濾器的調度事件。 以下示例演示如何將偵聽器附加到此組件: ```php <?php use Phalcon\Mvc\Dispatcher as MvcDispatcher; use Phalcon\Events\Event; use Phalcon\Events\Manager as EventsManager; $di->set( 'dispatcher', function () { // Create an event manager $eventsManager = new EventsManager(); // Attach a listener for type 'dispatch' $eventsManager->attach( 'dispatch', function (Event $event, $dispatcher) { // ... } ); $dispatcher = new MvcDispatcher(); // Bind the eventsManager to the view component $dispatcher->setEventsManager($eventsManager); return $dispatcher; }, true ); ``` 實例化的控制器自動充當調度事件的偵聽器,因此您可以將方法實現為回調: ```php <?php use Phalcon\Mvc\Controller; use Phalcon\Mvc\Dispatcher; class PostsController extends Controller { public function beforeExecuteRoute(Dispatcher $dispatcher) { // Executed before every found action } public function afterExecuteRoute(Dispatcher $dispatcher) { // Executed after every found action } } ``` >[warning] 事件偵聽器上的方法接受`Phalcon\Events\Event`對象作為它們的第一個參數 - 控制器中的方法不接受。 ## 轉發到其他動作 調度循環允許我們將執行流轉發到另一個控制器/動作。這對于檢查用戶是否可以訪問某些選項,將用戶重定向到其他屏幕或僅重用代碼非常有用。 ```php <?php use Phalcon\Mvc\Controller; class PostsController extends Controller { public function indexAction() { } public function saveAction($year, $postTitle) { // ... Store some product and forward the user // Forward flow to the index action $this->dispatcher->forward( [ 'controller' => 'posts', 'action' => 'index', ] ); } } ``` 請記住,進行`forward`與進行HTTP重定向不同。雖然他們顯然得到了相同的結果。`forward`不重新加載當前頁面,所有重定向都發生在單個請求中,而HTTP重定向需要兩個請求才能完成該過程。 更多轉發示例: ```php <?php // Forward flow to another action in the current controller $this->dispatcher->forward( [ 'action' => 'search' ] ); // Forward flow to another action in the current controller // passing parameters $this->dispatcher->forward( [ 'action' => 'search', 'params' => [1, 2, 3] ] ); ``` `forward` 操作接受以下參數: | 參數 | 描述 | | ------------ | ------------------------------------------------------- | | `controller` | 要轉發的有效控制器名稱。 | | `action` | 要轉發到的有效操作名稱。 | | `params` | 操作的參數數組。 | | `namespace` | 控制器所屬的有效命名空間名稱。 | ### 使用事件管理器 您可以使用`dispatcher::beforeForward`事件來更改模塊比重定向更容易和“更清潔”: ```php <?php use Phalcon\Di; use Phalcon\Events\Manager; use Phalcon\Mvc\Dispatcher; use Phalcon\Events\Event; $di = new Di(); $modules = [ 'backend' => [ 'className' => 'App\Backend\Bootstrap', 'path' => '/app/Modules/Backend/Bootstrap.php', 'metadata' => [ 'controllersNamespace' => 'App\Backend\Controllers', ], ], ]; $manager = new Manager(); $manager->attach( 'dispatch:beforeForward', function (Event $event, Dispatcher $dispatcher, array $forward) use ($modules) { $metadata = $modules[$forward['module']]['metadata']; $dispatcher->setModuleName($forward['module']); $dispatcher->setNamespaceName($metadata['controllersNamespace']); } ); $dispatcher = new Dispatcher(); $dispatcher->setDI($di); $dispatcher->setEventsManager($manager); $di->set('dispatcher', $dispatcher); $dispatcher->forward( [ 'module' => 'backend', 'controller' => 'posts', 'action' => 'index', ] ); echo $dispatcher->getModuleName(); // will display properly 'backend' ``` ## 準備參數 感謝`Phalcon\Mvc\Dispatcher`提供的掛鉤點,您可以輕松地將您的應用程序調整為任何URL架構;即您可能希望您的網址如下所示:`http://example.com/controller/key1/value1/key2/value`。由于參數是按照在操作的URL中定義的順序傳遞的,因此您可以將它們轉換為采用所需的模式: ```php <?php use Phalcon\Dispatcher; use Phalcon\Mvc\Dispatcher as MvcDispatcher; use Phalcon\Events\Event; use Phalcon\Events\Manager as EventsManager; $di->set( 'dispatcher', function () { // Create an EventsManager $eventsManager = new EventsManager(); // Attach a listener $eventsManager->attach( 'dispatch:beforeDispatchLoop', function (Event $event, $dispatcher) { $params = $dispatcher->getParams(); $keyParams = []; // Use odd parameters as keys and even as values foreach ($params as $i => $value) { if ($i & 1) { // Previous param $key = $params[$i - 1]; $keyParams[$key] = $value; } } // Override parameters $dispatcher->setParams($keyParams); } ); $dispatcher = new MvcDispatcher(); $dispatcher->setEventsManager($eventsManager); return $dispatcher; } ); ``` 如果所需的架構是:`http://example.com/controller/key1:value1/key2:value`,則需要以下代碼: ```php <?php use Phalcon\Dispatcher; use Phalcon\Mvc\Dispatcher as MvcDispatcher; use Phalcon\Events\Event; use Phalcon\Events\Manager as EventsManager; $di->set( 'dispatcher', function () { // Create an EventsManager $eventsManager = new EventsManager(); // Attach a listener $eventsManager->attach( 'dispatch:beforeDispatchLoop', function (Event $event, $dispatcher) { $params = $dispatcher->getParams(); $keyParams = []; // Explode each parameter as key,value pairs foreach ($params as $number => $value) { $parts = explode(':', $value); $keyParams[$parts[0]] = $parts[1]; } // Override parameters $dispatcher->setParams($keyParams); } ); $dispatcher = new MvcDispatcher(); $dispatcher->setEventsManager($eventsManager); return $dispatcher; } ); ``` ## 獲取參數 當路由提供命名參數時,您可以在控制器,視圖或任何其他繼承`Phalcon\Di\Injectable`的組件中接收它們。 ```php <?php use Phalcon\Mvc\Controller; class PostsController extends Controller { public function indexAction() { } public function saveAction() { // Get the post's title passed in the URL as parameter // or prepared in an event $title = $this->dispatcher->getParam('title'); // Get the post's year passed in the URL as parameter // or prepared in an event also filtering it $year = $this->dispatcher->getParam('year', 'int'); // ... } } ``` ## 準備動作 您還可以在調度循環之`前`為操作定義任意模式。 ### 操作名稱駝峰化 如果原始網址為:`http://example.com/admin/products/show-latest-products`,例如,您希望將`show-latest-products`傳遞給`ShowLatestProducts`,則需要以下代碼: ```php <?php use Phalcon\Text; use Phalcon\Mvc\Dispatcher as MvcDispatcher; use Phalcon\Events\Event; use Phalcon\Events\Manager as EventsManager; $di->set( 'dispatcher', function () { // Create an EventsManager $eventsManager = new EventsManager(); // Camelize actions $eventsManager->attach( 'dispatch:beforeDispatchLoop', function (Event $event, $dispatcher) { $dispatcher->setActionName( Text::camelize($dispatcher->getActionName()) ); } ); $dispatcher = new MvcDispatcher(); $dispatcher->setEventsManager($eventsManager); return $dispatcher; } ); ``` ### 刪除遺留的擴展名 如果原始URL始終包含`.php`擴展名: ```php http://example.com/admin/products/show-latest-products.php http://example.com/admin/products/index.php ``` 您可以在調度控制器/操作組合之前將其刪除: ```php <?php use Phalcon\Mvc\Dispatcher as MvcDispatcher; use Phalcon\Events\Event; use Phalcon\Events\Manager as EventsManager; $di->set( 'dispatcher', function () { // Create an EventsManager $eventsManager = new EventsManager(); // Remove extension before dispatch $eventsManager->attach( 'dispatch:beforeDispatchLoop', function (Event $event, $dispatcher) { $action = $dispatcher->getActionName(); // Remove extension $action = preg_replace('/\.php$/', '', $action); // Override action $dispatcher->setActionName($action); } ); $dispatcher = new MvcDispatcher(); $dispatcher->setEventsManager($eventsManager); return $dispatcher; } ); ``` ### 注入模型實例 在此示例中,開發人員希望檢查操作將接收的參數,以便動態注入模型實例。 控制器看起來像: ```php <?php use Phalcon\Mvc\Controller; class PostsController extends Controller { /** * Shows posts * * @param \Posts $post */ public function showAction(Posts $post) { $this->view->post = $post; } } ``` 方法`showAction`接收模型`\Posts`的一個實例,開發人員可以在調度準備參數的動作之前檢查這個: ```php <?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 () { // Create an EventsManager $eventsManager = new EventsManager(); $eventsManager->attach( 'dispatch:beforeDispatchLoop', function (Event $event, $dispatcher) { // Possible controller class name $controllerName = $dispatcher->getControllerClass(); // Possible method name $actionName = $dispatcher->getActiveMethod(); try { // Get the reflection for the method to be executed $reflection = new ReflectionMethod($controllerName, $actionName); $parameters = $reflection->getParameters(); // Check parameters foreach ($parameters as $parameter) { // Get the expected model name $className = $parameter->getClass()->name; // Check if the parameter expects a model instance if (is_subclass_of($className, Model::class)) { $model = $className::findFirstById($dispatcher->getParams()[0]); // Override the parameters by the model instance $dispatcher->setParams([$model]); } } } catch (Exception $e) { // An exception has occurred, maybe the class or action does not exist? } } ); $dispatcher = new MvcDispatcher(); $dispatcher->setEventsManager($eventsManager); return $dispatcher; } ); ``` 上面的例子已經簡化了。開發人員可以改進它,以便在執行之前在操作中注入任何類型的依賴關系或模型。 從3.1.x開始,調度程序還提供了一個選項,可以通過使用`Phalcon\Mvc\Model\Binder`在內部處理傳遞到控制器操作的所有模型。 ```php use Phalcon\Mvc\Dispatcher; use Phalcon\Mvc\Model\Binder; $dispatcher = new Dispatcher(); $dispatcher->setModelBinder(new Binder()); return $dispatcher; ``` >[warning] 由于Binder對象使用內部可能很重的Reflection Api,因此可以設置緩存。這可以通過在`setModelBinder()`中使用第二個參數來完成,該參數也可以接受服務名稱或僅通過將緩存實例傳遞給Binder構造函數。 它還引入了一個新接口`Phalcon\Mvc\Model\Binder\BindableInterface` ,它允許您定義控制器關聯模型,以允許模型在基本控制器中綁定。 例如,你有一個 `PostsController`繼承于基礎`CrudController`。你的`CrudController`看起來像這樣: ```php 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; } } ``` 在`PostsController`中,您需要定義控制器與哪個模型相關聯。這是通過實現`Phalcon\Mvc\Model\Binder\BindableInterface`來完成的,它將添加`getModelName()`方法,您可以從中返回模型名稱。它只返回一個模型名稱或關聯數組的字符串,其中key是參數名稱。 ```php use Phalcon\Mvc\Model\Binder\BindableInterface; use Models\Posts; class PostsController extends CrudController implements BindableInterface { public static function getModelName() { return Posts::class; } } ``` 通過聲明與`PostsController`關聯的模型,綁定器可以在將定義的模型傳遞到父顯示操作之前檢查控制器的`getModelName()`方法。 如果您的項目結構不使用任何父控制器,您當然仍然可以將模型直接綁定到控制器操作中: ```php 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; } } ``` >[warning] 目前,活頁夾僅使用模型主鍵來執行`findFirst()`。以上的示例路線是`/posts/show/{1}` ## 處理 Not-Found 異常 使用EventsManager,可以在調度程序在未找到控制器/操作組合時拋出異常時插入掛鉤點: ```php <?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 () { // Create an EventsManager $eventsManager = new EventsManager(); // Attach a listener $eventsManager->attach( 'dispatch:beforeException', function (Event $event, $dispatcher, Exception $exception) { // Handle 404 exceptions if ($exception instanceof DispatchException) { $dispatcher->forward( [ 'controller' => 'index', 'action' => 'show404', ] ); return false; } // Alternative way, controller or action doesn't exist 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(); // Bind the EventsManager to the dispatcher $dispatcher->setEventsManager($eventsManager); return $dispatcher; } ); ``` 當然,這個方法可以移動到獨立的插件類上,允許多個類在調度循環中產生異常時采取操作: ```php <?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'; // Handle 404 exceptions if ($exception instanceof DispatchException) { $action = 'show404'; } $dispatcher->forward( [ 'controller' => 'index', 'action' => $action, ] ); return false; } } ``` >[danger] 只有調度程序生成的異常和執行的操作中產生的異常才會在`beforeException`事件中得到通知。在偵聽器或控制器事件中生成的異常將重定向到最新的try/catch。 ## 實現自己的Dispatcher 必須實現 `Phalcon\Mvc\DispatcherInterface` 接口才能創建自己的調度程序,替換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>

                              哎呀哎呀视频在线观看