TYPO3 Routing Decisions: Core Route Enhancers vs Custom URL Logic
A decision guide for TYPO3 URL routing: when core route enhancers (Simple, Plugin, PageTypeDecorator, aspect mappers) suffice, when custom code is justified, and how to validate the round trip.
17 Aug 2025, 11:11 UTC

The decision you actually face
Since TYPO3 v9, every site carries its URL logic in config/sites/<identifier>/config.yaml. The practical question on any project is no longer "which URL extension do we install" but "which combination of core route enhancers covers our URL scheme, and where do we genuinely need custom code?" Getting this right matters because URLs are hard to change later: slugs get indexed, shared, and cached, and a wrong early choice means redirect maintenance for years.
The short answer for most projects: the three core enhancer types plus aspect mappers cover standard page, plugin, and record-detail URLs. Custom enhancers are the exception, not the rule. The guidance below assumes TYPO3 v11–v13 LTS; exact mapper names and options are version-sensitive, so verify against your LTS before committing.
Comparing the supported options
| Option | What it does | Best for | Trade-off |
|---|---|---|---|
| PageTypeDecorator | Maps suffixes or type numbers (e.g. .html, type=98) onto paths | Feeds, print views, legacy suffixes | Only decorates; does not route arguments |
| Simple enhancer | Maps path segments to query parameters | Static parameter schemes, pagination | Generic patterns can shadow more specific enhancers |
| Plugin enhancer | Routes Extbase plugin arguments (controller, action, record) | News detail pages, product views, any Extbase extension | Tied to Extbase plugin configuration |
| Aspect mappers | Convert between URL segment and stored value (e.g. PersistedAliasMapper for slug fields, StaticValueMapper) | Human-readable record URLs, bidirectional link generation | Requires a suitable TCA field (e.g. slug with eval uniqueInSite) |
| Custom enhancer (EnhancerInterface) | Arbitrary resolve/generate logic in PHP | Highly irregular legacy URL schemes | You own the code, tests, and upgrade burden across LTS versions |
Aspect mappers are not a separate enhancer — they plug into Simple and Plugin enhancers and work in both directions: resolving an incoming URL segment to a record, and generating the segment when Fluid builds a link. That round-trip property is what makes core routing safe to rely on.
Trade-offs that matter in practice
Core routing vs legacy RealURL-style solutions. RealURL belonged to the TYPO3 v8 era; on current LTS versions the core routing is the maintained, cacheable, configuration-driven path. What you give up is ad-hoc flexibility: RealURL tolerated irregular per-branch URL schemes more easily. If you are migrating such a scheme, prefer normalizing URLs plus 301 redirects over reproducing every quirk in a custom enhancer.
Ordering is semantic. Enhancers are evaluated in order and the first match wins. A broad Simple enhancer placed before a Plugin enhancer can swallow your extension's detail URLs. Put the most specific enhancers first and the most generic last.
Duplicate content risk. A misconfigured enhancer can leave the same record reachable under multiple URLs. Pair routing with canonical tags and use the core Redirects module for anything you retire.
Slug strategy is a one-way door. TYPO3 generates page slugs automatically, and record slugs come from a TCA slug field. Decide the generation pattern (which fields feed the slug, uniqueness scope) before launch. Changing it later invalidates indexed URLs, so any change must ship with redirects.
Custom logic belongs in the supported extension points. On v12/v13, implement custom URL behavior as an enhancer or via PSR-14 events and middleware — never as core patches. That keeps LTS-to-LTS upgrades manageable.
Concrete implementation: a news detail route
A typical Plugin enhancer with an aspect mapper in config/sites/main/config.yaml looks like this (adjust extension and plugin names to your setup):
routeEnhancers:
NewsPlugin:
type: Plugin
extension: News
plugin: Pi1
routes:
- routePath: '/article/{news-title}'
_controller: 'News::detail'
_arguments:
news-title: news
aspects:
news-title:
type: PersistedAliasMapper
tableName: tx_news_domain_model_news
routeFieldName: path_segmentThis maps /article/my-first-post to the news record whose path_segment field is my-first-post, and generates the same URL from f:link.action in Fluid. The record needs that slug field defined in TCA (typically with eval uniqueInSite) or the mapper has nothing reliable to resolve against.
Validating the result
Do not trust the YAML by reading it — validate the round trip:
- After editing, flush all caches from the backend (Admin Tools > Maintenance) or via CLI. A parse error in the site config surfaces when the frontend loads.
- In the backend Sites module, confirm the configuration loads and the enhancer section is intact.
- Render a page containing an
f:link.actionlink to the detail action and inspect the generated href — it should use your routePath, not?tx_news_pi1[news]=123. - Fetch the generated URL with
curl -I https://example.org/article/my-first-postfrom any machine that can reach the site. Expect a 200 response and a canonical link header or tag matching the URL. - Test the failure path: request a nonexistent slug and confirm you get a 404, not a 200 with empty content.
- If you changed slugs, verify old URLs return 301 to the new location via the Redirects module and
curl -Ion the old path.
Limitations
Enhancer options and available aspect mappers differ between TYPO3 11, 12, and 13 — check the routing documentation for your exact LTS before copying configuration. Core routing also assumes a single site configuration per site root; multi-domain or multi-tree setups need one config per site and careful base URL handling. If your validation shows URLs that core enhancers genuinely cannot express, that is the point at which a small custom enhancer is justified — not before.
0 replies
A thoughtful contribution can make all the difference. Be the first to share one.