Today we are going to talk about request routing and take a look at its customization process. Additionally, we will show you when it is necessary to create new routers and to customize the existing ones. Let’s get these things under the way.
What is request routing flow in Magento 2?
Routing in Magento is a process, that matches a request received in Magento, and the call of the corresponding control module. First of all, an application is created in the index.php file. Here starts the process of determining which of the routers will be called. Below you can see the parts of the code that are called.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 |
$app = $bootstrap->createApplication('Magento\Framework\App\Http'); $bootstrap->run($app); Далее у созданного application вызывается метод launch() /*** Magento\Framework\App\Bootstrap ***/ public function run(AppInterface $application) { /* …. */ $response = $application->launch(); $response->sendResponse(); /* …. */ } The “dispatch” method is also called here. It returns the result of the request. /*** Magento\Framework\App\Http ***/ public function launch() { /*** … ***/ /** @var \Magento\Framework\App\FrontControllerInterface $frontController */ $frontController = $this->_objectManager->get('Magento\Framework\App\FrontControllerInterface'); $result = $frontController->dispatch($this->_request); /*** … ***/ return $this->_response; } |
If you look at what the “dispatch” method contains, it becomes clear how the request is processed and the router is selected. Let us take a look at this code.
Here each of the routers ($this ➔ _routerList) is checked for compliance with the query. If found, the \”Magento\Framework\App\Action” object will be returned.
If none of the routers finds a matching query, the standard noroute action class is called.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 |
l /** * Class FrontController * @package Magento\Framework\App */ public function dispatch(RequestInterface $request) { /******* .... *********/ /** @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; } /****** … ******/ return $result; } } |
It is easy to notice that the list of routers ($this ➔ _routerList) is processed in the cycle. By default this list consists of standard routers implementing RouterInterface, which are called in the following sequence:
- Base Router
- CMS Router
- UrlRewrite Router
- Default Router
Customize request routing
Magento allows you to add your router to this list. Now let’s consider an example of creating a custom router.
The registration of a new router takes place in di.xml. Here you can define the class that is responsible for processing the request (item name = “class”), the priority of calling the router (item name = “sortOrder”)
1 2 3 4 5 6 7 8 9 10 11 12 13 14 |
<?xml version="1.0"?> <config xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="urn:magento:framework:ObjectManager/etc/config.xsd"> <type name="Magento\Framework\App\RouterList"> <arguments> <argument name="routerList" xsi:type="array"> <item name="newreqrouter" xsi:type="array"> <item name="class" xsi:type="string">BelVG\NewRequestRouter\Controller\Router</item> <item name="disable" xsi:type="boolean">false</item> <item name="sortOrder" xsi:type="string">30</item> </item> </argument> </arguments> </type> </config> |
The request will be processed directly in the Router class.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 |
/* BelVG\NewRequestRouter\Controller\Router*/ namespace BelVG\NewRequestRouter\Controller; /** * Class Router * @package BelVG\NewRequestRouter\Controller */ class Router implements \Magento\Framework\App\RouterInterface { /** * @var \Magento\Framework\App\ActionFactory */ protected $actionFactory; /** * Response * * @var \Magento\Framework\App\ResponseInterface */ protected $_response; /** * @param \Magento\Framework\App\ActionFactory $actionFactory * @param \Magento\Framework\App\ResponseInterface $response */ public function __construct( \Magento\Framework\App\ActionFactory $actionFactory, \Magento\Framework\App\ResponseInterface $response ) { $this->actionFactory = $actionFactory; $this->_response = $response; } /** * Validate and Match * * @param \Magento\Framework\App\RequestInterface $request * @return bool */ public function match(\Magento\Framework\App\RequestInterface $request) { $identifier = trim($request->getPathInfo(), '/'); if(strpos($identifier, 'anytestrequest') !== false) { $request->setModuleName('newrequest')->setControllerName('test') ->setActionName('index'); } else { return; } return $this->actionFactory->create( 'Magento\Framework\App\Action\Forward', ['request' => $request] ); } } |
You can check out the full version of the example of adding a new router here.
When it is necessary to create new routers and to customize the existing ones
Sometimes you may need to create your own router or customize an existing one. One good example is the “blog” module, when you need to redirect seo-friendly URLs to the corresponding posts. For this purpose, the module creates its own Router, which distributes the queries.
Also, when migrating from any other platform to Magento, you may need to retain the connection between the old URLs and the new addresses. To do this, you can also use an additional router, which will contain the logic of finding a matching URL (old_webshop_url – magento_webshop).
Customization of an existing router is required, when there is no way to bypass the processing of a standard router request. For example, the router is run in the queue earlier than the custom one and doesn’t find the path required for customization.
Check out a related article to find out more about request routing in Magento 2.