5

I would like an explanation of the dispatch and execute functions, the differences between them, when they are/should be used and how.

Please limit your answer to Magento 2

  • Have you looked at the code and/or documentation, or do you expect an essay from someone? – Robbie Averill Jun 14 '16 at 10:07
  • 1
    It's a question website. Unless my question is duplicated or against the guidelines, don't complain about me asking. – LM_Fielding Jun 14 '16 at 10:18
13

I'm assuming here you're referring to the Action class dispatch() method and not about the Magento\Framework\Event\ManagerInterface method (that dispatches an event to be used in the observer).

In general terms:

  • the front controller Magento\Framework\App\FrontController dispatches a request and gets a result object.
  • the app Magento\Framework\App\Http in the launch() method copies HTML to the response object.
  • the bootstrap Magento\Framework\App\Bootstrap flushes that HTML from the response object to the browser.

An action class usually extends Magento\Framework\App\Action here's a class diagram:

enter image description here

The ActionInterface has only two methods: dispatch() and response()

To get a good overview of the high level execution flow here's another diagram:

enter image description here

Here's a summary of the flow:

  • The FrontController::dispatch() is called from the app::launch()
  • It finds the correct router, which then finds the correct action class.
  • The front controller class an action class that then calls dispatch(). Magento\Framework\App\Action\Action is where the dispatch() method is implement; it then calls the execute() method

To make more sense, I reckon you can check the dispatch() method from Magento\Framework\App\FrontController which performs action and generate the response:

public function dispatch(RequestInterface $request)
{
    \Magento\Framework\Profiler::start('routers_match');
    $routingCycleCounter = 0;
    $result = null;
    while (!$request->isDispatched() && $routingCycleCounter++ < 100) {
        /** @var \Magento\Framework\App\RouterInterface $router */
        foreach ($this->_routerList as $router) {
            try {
                $actionInstance = $router->match($request);
                if ($actionInstance) {
                    $request->setDispatched(true);
                    $this->response->setNoCacheHeaders();
                    if ($actionInstance instanceof \Magento\Framework\App\Action\AbstractAction) {
                        $result = $actionInstance->dispatch($request);
                    } else {
                        $result = $actionInstance->execute();
                    }
                    break;
                }
            } catch (\Magento\Framework\Exception\NotFoundException $e) {
                $request->initForward();
                $request->setActionName('noroute');
                $request->setDispatched(false);
                break;
            }
        }
    }
    \Magento\Framework\Profiler::stop('routers_match');
    if ($routingCycleCounter > 100) {
        throw new \LogicException('Front controller reached 100 router match iterations');
    }
    return $result;
}

Unlike in M1, where the router would implement everything, in M2 the action instance implements dispatch() and it must also implement execute()

The execute() method actually processes the URL. When someone enters a URL, it winds up in the action class (of a controller). It is where you implement your logic.

The dispatch() method is less likely to be implemented in custom modules. Most cases where you will have to do so are:

  • Check whether a customer is logged in (see here)
  • Check whether a payment method is enabled (see here)

Source: Fundamentals of Magento 2

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.