Magento 2 Routing

In this article, we will talk about an important part in Magento 2 Routing. The Route will define name for a module which we can use in the url to find the module and execute the controller action.

Magento 2 request flow

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

http://example.com/index.php/front_name/controller/action

In that url, 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 router.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/action: index.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 find out the controller action for this request, that action will be called and executed.

Create custom route on frontend/admin

In this part, we will use a simple module Mageplaza_HelloWorld. Please follow the previous article to know how to create and register a Module in Magento 2.

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

Frontend route

To register a frontend route, we must create a routes.xml file:

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

<?xml version="1.0"?>
<config xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="urn:magento:framework:App/etc/routes.xsd">
   <!--Use router 'standard' for frontend route-->
   <router id="standard">
       <!--Define a custom route with id and frontName-->
       <route id="example" frontName="example">
           <!--The module which this route match to-->
           <module name="Mageplaza_HelloWorld" />
       </route>
   </router>
</config>

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

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

The url to this module should be:

http://example.com/index.php/examplefront/controller/action

And the layout handle for this action is: exampleid_controller_action.xml So with this example path, you must create the action class in this folder: {module_path}/Controller/Controller/Action.php

Admin route

This route will be same as the frontend route but you must declare it in adminhtml folder with router id is admin.

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

<?xml version="1.0"?>
<config xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="urn:magento:framework:App/etc/routes.xsd">
   <!--Use router 'standard' for frontend route-->
   <router id="admin">
       <!--Define a custom route with id and frontName-->
       <route id="example" frontName="example">
           <!--The module which this route match to-->
           <module name="Mageplaza_HelloWorld"/>
       </route>
   </router>
</config>

The url of the admin page is the 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:

http://example.com/index.php/admin/example/blog/index

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

{module_path}/Controller/Adminhtml/Blog/Index.php

Use route to rewrite controller

In this path, we will see how to rewrite a controller with router. As above path, 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 system provide the attribute before/after to config the module sort order which define what module controller will be find 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/Mageplaza/HelloWorld/etc/frontend/routes.xml

<?xml version="1.0"?>
<config xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="urn:magento:framework:App/etc/routes.xsd">
   <!--Use router 'standard' for frontend route-->
   <router id="standard">
       <!--Define a custom route with id and frontName-->
       <route id="example" frontName="example">
           <!--The module which this route match to-->
           <module name="Mageplaza_HelloWorld" />
       </route>
       <route id="customer">
           <module name="Mageplaza_HelloWorld" before="Magento_Customer" />
       </route>
   </router>
</config>

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

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

You can also use this to have a second module with the same router as another module. For example, with above declare, you can use route ‘customer’ for your controller action. If you have controller ‘Blog’ and action ‘Index.php’ you can use this url:

http://example.com/customer/blog/index




Next tutorial:



Enjoyed the tutorial? Spread it to your friends!

magento-2-module-development
hello-world
routing

Comments for Magento 2 Routing

Please leave comments if you have any questions, feedbacks.

You also may like these Magento 2 Extensions

One Step Checkout

$199
10 reviews

Layered Navigation

$149
12 reviews

Affiliate

$149
3 reviews

FAQ

$149
10 reviews

Zoho CRM

$249
3 reviews

Store Locator

$199
3 reviews

Shop By Brand

$99
3 reviews

Better Blog

FREE
8 reviews

People also searched for:

  • magento 2 routing
  • Magento 2 request flow
  • routing for magento 2