Choosing a TYPO3 Route Enhancer: A Decision Guide for Readable, Localized URLs
TYPO3 v9+ moved routing into the core site config. This guide compares route enhancers and aspect mappers, shows a working Extbase configuration, and covers validation and RealURL migration.
27 Mar 2026, 05:08 UTC

The decision you actually have to make
Since TYPO3 v9 LTS, URL routing is a core feature configured per site in config/sites/<identifier>/config.yaml. The legacy RealURL extension is gone, so the practical question is no longer "which extension handles URLs" but "which core route enhancer fits each type of link on this site." Pick wrong and you get ambiguous routes, links that render but 404 when visited, or a slug strategy that collapses under a large record set.
The constraints that drive the decision:
- Do the URLs point to pages, plugin arguments, or database records from an extension?
- How many records are involved — dozens, or tens of thousands?
- Do editors need to hand‑edit slugs, and must slugs differ per language?
- Are you migrating from RealURL, meaning existing inbound links must keep working?
Comparing the supported options
| Option | Best for | Slug storage | Main trade‑off |
|---|---|---|---|
| PageTypeDecorator | Mapping type parameters (e.g., print view, sitemap.xml) to path suffixes | None | Only handles page type numbers, not records |
| Simple enhancer | Non‑Extbase plugins with a few GET parameters | None | Parameters map 1:1 to segments; no record titles in URLs |
| Plugin enhancer | Extbase plugins where controller/action should appear in the path | None by itself | Needs aspects for record arguments or URLs stay numeric |
| Extbase enhancer | Extbase extensions with namespaced arguments | None by itself | Most configuration surface; easy to create ambiguous routes |
| PersistedAliasMapper (aspect) | Record sets where editors control slugs | One slug field per record | Requires unique‑value handling and slug updates on rename |
| PersistedPatternMapper (aspect) | Large record sets | None — built from a pattern at runtime | No per‑record editorial control over the slug |
| Custom enhancer (EnhancerInterface) | Exotic URL schemes nothing else covers | Your choice | You must implement both generation and inbound resolving |
The two persisted mappers are the decision that matters most for extension records. PersistedAliasMapper reads a slug stored in a database column on each record. Editors can change it, and it can be translatable — which you need if each language gets its own slug. The cost: you must enforce uniqueness (the core slug generator handles this with a unique‑in‑pid or site‑wide eval) and decide what happens when a record title changes. PersistedPatternMapper builds the path from a configurable pattern (for example {title}-{uid}) with nothing stored per record, so it scales to huge tables and never goes stale — but editors cannot override individual URLs.
Localization constraint
Per‑language URL prefixes come from the site's language configuration (base variants and locale settings) and work regardless of enhancer. The real constraint is the record slug: if a news article must be /en/blog/my-post in English and /de/blog/mein-beitrag in German, the slug field must be translatable in TCA and you must use PersistedAliasMapper. A PatternMapper built from the title will localize automatically only if the pattern field itself is translated; verify this on your data model before committing.
Concrete configuration: Extbase plugin with alias‑mapped records
The following goes in config/sites/main/config.yaml on the site that hosts the plugin page. Edit it via the backend Site Management module or directly on the file; no special permissions beyond backend admin or file access are needed. Placeholders: 12 is the page UID containing the plugin, tx_blog is your extension's argument namespace, Post is your Extbase model.
routeEnhancers:
BlogPlugin:
type: Extbase
limitToPages: [12]
extension: Blog
plugin: Pi1
routes:
-
routePath: '/post/{post_title}'
_controller: 'Post::show'
_arguments:
post_title: post
defaultController: 'Post::list'
aspects:
post_title:
type: PersistedAliasMapper
tableName: tx_blog_domain_model_post
routeFieldName: slug
Key points and risks:
limitToPagesconfines the enhancer to the plugin page. Without it, the route can match on unintended pages and produce ambiguous URLs.- The
slugfield must exist in TCA fortx_blog_domain_model_postwith slug generation configured (typically'type' => 'slug'in the column config). If a record has an empty slug, link generation falls back or fails depending on version — populate slugs before enabling the aspect. - Adding a
requirementsmap (e.g., a regex for UID parameters) prevents a route from swallowing segments meant for another route. Ambiguity here is the most common cause of "link renders, page 404s." - After changing this file, flush all caches (backend: Admin Tools > Maintenance > Flush, or
vendor/bin/typo3 cache:flushon the CLI). Route configuration is cached; stale caches are the most common reason a correct config appears broken.
Validating the result
- Clear caches, then visit a frontend page that links to a record. Inspect the generated
href— it should match yourroutePathpattern, e.g./blog/post/my-first-post. - Open that URL directly in a fresh browser session. This tests inbound resolving, which is a separate code path from generation. A link that renders but 404s when visited means your route is asymmetric — usually a missing
_argumentsmapping or a requirements regex that rejects the generated value. - Test each configured language variant and confirm the locale prefix and (if applicable) the translated slug.
- In the backend, check Site Management and the Redirects module for unexpected 404s after the change.
Migrating from RealURL
Enhancer‑generated paths will almost certainly differ from RealURL's alias paths, so existing inbound links and search rankings are at risk. Before regenerating slugs: run the core upgrade wizards, export or record a sample of legacy URLs, and create redirects (the core redirects module supports this) from old paths to new ones. Then diff a sample of newly generated URLs against the legacy list to confirm coverage. Do not regenerate slugs on a live site without the redirect plan in place.
Limitations and version caution
Enhancer keys and aspect options are version‑sensitive: configuration valid in one LTS may be deprecated in the next. The example above reflects the established v9–v12‑era structure, but confirm every key against the official documentation changelog for your target LTS before deploying. Custom enhancers implementing EnhancerInterface remain the escape hatch for exotic schemes, but budget for implementing and testing both directions — generation and resolving — since asymmetry is silent until someone clicks a link.
0 replies
A thoughtful contribution can make all the difference. Be the first to share one.