Routing is the most important piece of any application or framework. This post covers the request flow of magento or routing process in magento2. The Route will define name for a module, which we may use in the url to find the module and execute the controller action.

In Magento 2, the request url will be like this:

In that url string, you will see the front_name, which will be use to find the module. The router define this name for each module by define in routes.xml which we will see more detail bellow.

When you make a request in Magento 2, it will follow this flow to find the controller/actionindex.php → HTTP app → FrontController → Routing → Controller processing → etc

The FrontController will be call in Http class to routing the request which will find the controller/action match.

File: vendor/magento/framework/App/FrontController.php

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

As you can see in this dispatch() method, the router list will be loop to find the match one with this request. If it will find out the controller action for this request, in this case action will be called and executed.

Custom route on frontend/admin

In this piece, we will use a simple module Mrmage_HelloWorld.

We will find how to create a frontend route, admin route and how to use route to rewrite controller.

Define frontend routes

For register frontend route, we should create a routes.xml file:

File: app/code/Mrmage/HelloWorld/etc/frontend/routes.xml



    
    
        
        
            
            
        
    

Please look into the code, you will see it’s very simple to register a route. You should use the standard router for the frontend. This route will have a child which define the module for it and 2 attributes:

  • This id attribute is a unique string which will identify this route. You will use the string to declare layout handler for action of this module
  • The frontName attribute is also a unique string, which will be display on the url request. For example, if you declare a route like this:
 <route frontName="helloworld" id="helloworld">

The url to this module should be:

layout handler for action is: helloworld_controller_action.xml So with this example path, you should create the action class in this folder: {namespace}/{module}/Controller/{Controller}/{Action}.php

Define Admin routes

This route will be same as the frontend route but you should declare it at adminhtml directory with router id is admin.

File: app/code/Mrmage/HelloWorld/etc/adminhtml/routes.xml



    
    
        
        
            
            
        
    

Url of admin page is same structure with frontend page, but the admin_area name will be added before route_frontName to recognize this is a admin router. For example, the url of admin cms page:

This controller action for admin page will be added within of the folder Controller/Adminhtml. For example for above url:

{namespace}/{module}/Controller/Adminhtml/{Controller}/{Action}.php

How to use route to rewrite controller

In this piece, we will see how to rewrite a controller with router. As above piece, you can see each route will have an id attribute to identify. So what happen, if we define 2 route with the same id attribute?

The answer is that the controller action will be find in both of that modules. Magento 2 provide the attribute before/after for config the module sort order, which define what module controller will be use first. This’s the logic for the controller rewrite.

For example, if we want to rewrite the controller customer/account/login, we will define more route in the route.xml like this:

File: app/code/Mrmage/HelloWorld/etc/frontend/routes.xml



   
   
        
        
            
            
        
       
           
       
   

And the controller file: app/code/Mrmage/HelloWorld/Controller/Account/Login.php

So in this case frontController find the Login action in our module first, if it’s found, it will execute and the Login action of Magento_Customer will not be run. We are successful rewrite a controller.