URL Rewrites
Understanding how Magento processes user-friendly URLs, the url_rewrite table, and complete URL processing workflow.
URL Rewrite System Overview
What are URL Rewrites?
User-Friendly URLs
URL rewrites transform technical URLs into SEO-friendly, readable URLs:
Technical URL (Without Rewrite)
catalog/product/view/id/123
Not user-friendly, not SEO-optimized
User-Friendly URL (With Rewrite)
blue-widget.html
Clean, readable, SEO-friendly
URL Key Attribute
Defining User-Friendly URLs
The URL key is the attribute/column that defines the user-friendly URL for:
- Products
- Categories
- CMS pages
How URL Keys Work:
- Manual Entry: Admin can specify custom URL key
- Auto-Generation: If empty, Magento slugifies the name
- Converts to lowercase
- Replaces spaces with hyphens
- Removes special characters
- Database Storage: Creates row in
url_rewritetable
Example: Product Name → URL Key
| Product Name | Auto-Generated URL Key |
|---|---|
| Blue Widget | blue-widget |
| Men's Running Shoes | mens-running-shoes |
| 32" LED TV (4K) | 32-led-tv-4k |
Changing URL Keys
How to Modify URL Keys
Products:
Admin Path: Catalog → Products → Edit Product → Search Engine Optimization
URL Key: blue-widget
Categories:
Admin Path: Catalog → Categories → Edit Category → Search Engine Optimization
URL Key: electronics
CMS Pages:
Admin Path: Content → Pages → Edit Page
URL Key: about-us
Category Path in Product URLs
"Use Categories Path for Product URLs"
Configuration Path: Stores → Configuration → Catalog → Catalog → Search Engine Optimizations
Setting: Use Categories Path for Product URLs = Yes/No
Impact:
Disabled (No)
blue-widget.html
Product URL only
Enabled (Yes)
electronics/gadgets/blue-widget.html
Category path included
electronics/blue-widget.htmlelectronics/gadgets/blue-widget.htmlnew-arrivals/blue-widget.html
The url_rewrite Table
Database Structure
Magento stores all URL rewrites in the url_rewrite table:
Key Columns:
| Column | Description | Example |
|---|---|---|
request_path |
User-friendly URL | blue-widget.html |
target_path |
Internal Magento path | catalog/product/view/id/123 |
entity_type |
Type of entity | product, category, cms-page |
entity_id |
Entity's database ID | 123 |
redirect_type |
HTTP redirect code | 0 (no redirect), 301, 302 |
store_id |
Store view ID | 1 |
Example Query:
SELECT
request_path,
target_path,
entity_type,
entity_id,
redirect_type
FROM url_rewrite
WHERE request_path = 'blue-widget.html'
AND store_id = 1;
Redirect Types
HTTP Redirect Codes
| redirect_type | HTTP Code | Name | Use Case |
|---|---|---|---|
0 |
- | No Redirect | Standard URL rewrite (internal) |
301 |
301 | Permanent Redirect | URL changed permanently (passes SEO) |
302 |
302 | Temporary Redirect | URL temporarily moved (doesn't pass SEO) |
Best Practice for Redirects:
- Magento url_rewrite: Works but slower (PHP processing)
- Nginx/Apache: Faster (handled at web server level)
- Recommendation: Use server-level redirects for high traffic sites
URL Processing Flow
Complete Request Processing
Step-by-Step Flow:
- Request arrives at
pub/index.php - Bootstrap initializes -
\Magento\Framework\App\Bootstrap - Application launches -
\Magento\Framework\App\Httpfor web requests - FrontController initialized - Via ObjectManager
- Router loop begins - FrontController iterates through routers
- First match wins - Router returns ActionInterface
- Request marked dispatched - Stops router loop
- Action executes - Generates response
FrontController Dispatch Logic:
// Simplified from \Magento\Framework\App\FrontController
public function dispatch(RequestInterface $request)
{
// Loop while not dispatched
while (!$request->isDispatched()) {
// Try each router
foreach ($this->routerList as $router) {
$actionInstance = $router->match($request);
if ($actionInstance) {
// Mark as dispatched
$request->setDispatched(true);
// Execute action
return $actionInstance;
}
}
}
}
$request->setDispatched(true) to stop the while loop, or the router loop will continue infinitely!
Router Execution Order
Default Router Sequence
Routers are executed in sortOrder (priority) sequence:
| Order | Router | Class | Purpose |
|---|---|---|---|
| 1 | Robots | \Magento\Robots\Controller\Router |
Handles /robots.txt requests |
| 2 | URL Rewrite | \Magento\UrlRewrite\Controller\Router |
Processes URL rewrites from database |
| 3 | Standard | \Magento\Framework\App\Router\Base |
Handles standard 3-chunk URLs |
| 4 | CMS | \Magento\Cms\Controller\Router |
Matches CMS pages |
| 5 | Default (404) | \Magento\Framework\App\Router\DefaultRouter |
Fallback - shows 404 page |
URL Rewrite Router Configuration
Router Registration Example
From vendor/magento/module-url-rewrite/etc/frontend/di.xml:
<?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="urlrewrite" xsi:type="array">
<item name="class" xsi:type="string">
Magento\UrlRewrite\Controller\Router
</item>
<item name="disable" xsi:type="boolean">false</item>
<item name="sortOrder" xsi:type="string">40</item>
</item>
</argument>
</arguments>
</type>
</config>
sortOrder of 40 places URL Rewrite router after Base router (20) but before CMS router (60).
Finding Pages from URLs
Determining Which Page Corresponds to a URL
Method 1: Query url_rewrite Table
SELECT * FROM url_rewrite
WHERE request_path LIKE '%blue-widget%';
Method 2: Get Entity Information
SELECT
ur.request_path,
ur.target_path,
ur.entity_type,
ur.entity_id,
ur.redirect_type,
p.sku,
p.name
FROM url_rewrite ur
LEFT JOIN catalog_product_entity_varchar p
ON ur.entity_id = p.entity_id
WHERE ur.request_path = 'blue-widget.html'
AND ur.entity_type = 'product';
Method 3: Check target_path
-- If target_path shows:
catalog/product/view/id/123
-- Product ID is 123
Quick Lookup Steps:
- Search
request_pathcolumn for URL segment - Check
entity_type(product, category, cms-page) - Get ID from
entity_idor parsetarget_path - Verify
store_idmatches expected store
Debugging URL Rewrites
Troubleshooting Techniques
1. Set Breakpoint in FrontController
// File: vendor/magento/framework/App/FrontController.php
// Method: dispatch()
// Set breakpoint here to watch router execution
foreach ($this->routerList as $router) {
$actionInstance = $router->match($request);
}
2. Check URL Rewrite Table
bin/magento indexer:reindex catalog_url
3. Enable URL Rewrite Logging
// Add in UrlRewrite Router
$this->logger->debug('URL Rewrite: ' . $request->getPathInfo());
4. Clear Caches
bin/magento cache:clean config full_page
Best Practices
Do's
- Use descriptive URL keys
- Create 301 redirects for old URLs
- Keep URL keys consistent
- Use hyphens, not underscores
- Reindex after bulk URL changes
- Test URL changes before deploy
- Monitor url_rewrite table size
- Use server-level redirects when possible
Don'ts
- Don't use special characters in URL keys
- Don't create duplicate URL keys
- Don't change URLs without redirects
- Don't forget to reindex
- Don't ignore 404 errors
- Don't create circular redirects
- Don't use long URL keys (>255 chars)
Exam Tips
Key Points to Remember
- URL Key: Attribute that defines user-friendly URL
- Auto-generation: Magento slugifies name if URL key is empty
- url_rewrite table: Stores all URL rewrites
- Key columns: request_path, target_path, entity_type, entity_id, redirect_type
- Category paths: "Use Categories Path for Product URLs" creates multiple rewrites
- Redirect types: 0 (no redirect), 301 (permanent), 302 (temporary)
- Processing flow: Bootstrap → FrontController → Router loop → Action
- Router order: Robots → URL Rewrite → Standard → CMS → Default
- URL Rewrite router: sortOrder 40, runs before Standard router
- Finding pages: Query url_rewrite table by request_path
- setDispatched(): Must be called to stop router loop
- Configuration: Stores → Configuration → Catalog → SEO