Multiple Routes Configuration
A single module can register multiple routes for different URL patterns.
Multiple routes in 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">
<router id="standard">
<route id="vendor_blog" frontName="blog">
<module name="Vendor_Blog"/>
</route>
<route id="vendor_news" frontName="news">
<module name="Vendor_Blog"/>
</route>
<route id="vendor_blog_admin" frontName="blog_admin">
<module name="Vendor_Blog" area="adminhtml"/>
</route>
</router>
</config>
URL mapping:
blog/post/view/id/1 → Vendor_Blog::Post::view
blog/category/list → Vendor_Blog::Category::list
news/article/read → Vendor_Blog::Article::read
blog_admin/post/edit → Vendor_Blog::Post::edit (admin area)
Route attributes:
id— Unique route identifier within the routerfrontName— First URL segment (the front controller name)area— Optional: restrict to specific area (adminhtml, frontend)
Area-specific routes:
<!-- etc/frontend/routes.xml -->
<router id="standard">
<route id="vendor_blog" frontName="blog">
<module name="Vendor_Blog"/>
</route>
</router>
<!-- etc/adminhtml/routes.xml -->
<router id="admin">
<route id="vendor_blog_admin" frontName="blog_admin">
<module name="Vendor_Blog" area="adminhtml"/>
</route>
</router>
Router Class Overrides
Magento allows overriding the default router class for custom URL matching logic.
Default router:
<router id="standard">
<class>Magento\Framework\App\Router\Base</class>
</router>
Custom router:
<router id="standard">
<class>Vendor\Module\Router\CustomRouter</class>
</router>
Custom router class:
<?php
namespace Vendor\Module\Router;
use Magento\Framework\App\Action\Forward;
use Magento\Framework\App\Action\Redirect;
use Magento\Framework\App\RequestInterface;
use Magento\Framework\App\RouterInterface;
class CustomRouter implements RouterInterface
{
public function __construct(
private \Magento\Framework\App\ActionFactory $actionFactory,
private \Magento\Framework\App\Config\ScopeConfigInterface $config
) {}
public function match(RequestInterface $request): ?ActionInterface
{
$urlKey = trim($request->getPathInfo(), '/');
// Custom URL matching logic
if (preg_match('/^product\/([\w-]+)$/', $urlKey, $matches)) {
$request->setRouteName('catalog');
$request->setControllerName('product');
$request->setActionName('view');
$request->setParam('url_key', $matches[1]);
return $this->actionFactory->create(
\Magento\Catalog\Controller\Product\View::class
);
}
return null; // Let next router handle it
}
}
Multiple routers (priority order):
<!-- Routers execute in order -->
<router id="standard">
<class>Magento\Framework\App\Router\Base</class>
</router>
<!-- Custom router added via di.xml -->
<type name="Magento\Framework\App\Router\Base">
<arguments>
<argument name="actionList" xsi:type="array">
<item name="custom_router" xsi:type="object">
Vendor\Module\Router\CustomRouter
</item>
</argument>
</arguments>
</type>
Route Priority and Matching
Understanding how Magento matches URLs to routes and controllers.
URL structure:
https://example.com/{frontName}/{controller}/{action}/{param}/{value}
Example:
https://example.com/blog/post/view/id/5
└─ frontName ─┘└─ controller ─┘└─ action ─┘└─ param/value ─┘
Route matching process:
1. Extract frontName from URL
2. Find matching route in routes.xml
3. Map frontName → controller → action
4. Execute action class
Controller mapping:
frontName: blog
controller: post
action: view
→ Vendor/Blog/Controller/Post/View.php
Custom URL key in controller:
namespace Vendor\Blog\Controller\Post;
use Magento\Framework\App\Action\Action;
use Magento\Framework\App\Action\Context;
class View extends Action
{
public function execute()
{
$id = $this->getRequest()->getParam('id');
$urlKey = $this->getRequest()->getParam('url_key');
// URL key can be used for custom matching
if ($urlKey) {
// Load by URL key instead of ID
}
return $this->resultFactory->create(
\Magento\Framework\View\Result\Page::class
);
}
}
Priority rules:
1. Exact match wins over pattern match
2. First matching router returns the action
3. If no router matches, 404 is returned
4. URL rewrites are checked before routes
URL Rewrite Integration
Magento's URL rewrite system integrates with routing for SEO-friendly URLs.
URL rewrite storage:
url_rewrite table:
├── entity_type (product, category, cms)
├── entity_id
├── request_path (/my-product.html)
├── target_path (catalog/product/view/id/5)
└── redirect_type (301, 302)
Custom URL rewrite in code:
$rewrite = $this->rewriteFactory->create();
$rewrite->setEntityType('custom');
$rewrite->setEntityId(123);
$rewrite->setRequestPath('custom/url.html');
$rewrite->setTargetPath('custom_module/controller/action/id/123');
$rewrite->save();
Route + URL rewrite flow:
1. User visits: /my-product.html
2. URL rewrite table lookup
3. Found: target_path = catalog/product/view/id/5
4. Route: frontName = catalog
5. Controller: Product::View
6. Action executed with id=5
Custom URL rewrite module:
<?php
namespace Vendor\SEO\Observer;
use Magento\Framework\Event\Observer;
use Magento\Framework\Event\ObserverInterface;
class ProductUrlObserver implements ObserverInterface
{
public function execute(Observer $observer)
{
$product = $observer->getEvent()->getProduct();
// Create custom URL rewrite for product
$this->createRewrite(
$product->getUrlKey(),
'catalog/product/view/id/' . $product->getId()
);
}
}
Debugging routes:
# Check route configuration
php bin/magento dev:router:list
# View URL rewrites
php bin/magento urlrewrite:index
# Clear URL rewrites
php bin/magento urlrewrite:reindex
Quiz
1. What attribute in routes.xml sets the first URL segment?
2. How does URL mapping work for blog/post/view?
3. What happens when no router matches a URL?
4. Where are URL rewrites stored?
Flashcards
Question
What does frontName represent in a URL?
Click to reveal answer
Answer
The first path segment that maps to a route (e.g., 'blog' in /blog/post/view)
Question
What is the controller mapping for catalog/product/view?
Click to reveal answer
Answer
Catalog controller, Product class, view action
Question
How do multiple routes resolve?
Click to reveal answer
Answer
First matching router returns the action; priority goes to exact matches
Question
What is checked before routes during URL resolution?
Click to reveal answer
Answer
URL rewrites (from url_rewrite table)
Question
What CLI command lists available routes?
Click to reveal answer
Answer
php bin/magento dev:router:list
Revision Notes
Key Takeaways
- 1. A single module can have multiple routes with different frontNames
- 2. Router classes can be overridden for custom URL matching
- 3. URL structure: frontName/controller/action/params
- 4. URL rewrites are checked before route matching
- 5. Route priority favors exact matches over patterns
- 6. area attribute restricts routes to specific areas
Interview Tips
- • Explain the URL-to-controller mapping process
- • Describe how to create a custom router
- • Discuss URL rewrite integration with routing
- • Know how to debug route configuration
Cheat Sheet
routes.xml Cheat Sheet
URL Structure:
/frontName/controller/action/param/value
Route attributes:
- id: Unique route identifier
- frontName: First URL segment
- area: adminhtml/frontend (optional)
Controller mapping:
frontName/post → Vendor/Module/Controller/Post.php
frontName/post/view → Vendor/Module/Controller/Post/View.php
Priority:
- URL rewrites (url_rewrite table)
- Exact route match
- First matching router
- 404 if nothing matches
CLI:
- dev:router:list — List routes
- urlrewrite:index — Reindex rewrites