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/123Not user-friendly, not SEO-optimized
User-Friendly URL (With Rewrite)
blue-widget.htmlClean, 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-widgetCategories:
Admin Path: Catalog → Categories → Edit Category → Search Engine Optimization
URL Key: electronicsCMS Pages:
Admin Path: Content → Pages → Edit Page
URL Key: about-usCategory 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.htmlProduct URL only
Enabled (Yes)
electronics/gadgets/blue-widget.htmlCategory path included
- electronics/blue-widget.html
- electronics/gadgets/blue-widget.html
- new-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 123Quick 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_url3. Enable URL Rewrite Logging
// Add in UrlRewrite Router
$this->logger->debug('URL Rewrite: ' . $request->getPathInfo());4. Clear Caches
bin/magento cache:clean config full_pageBest 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
