Routing aspects: mapping route placeholders to URLs
A route placeholder like {conference_ is just a named capture group —
it matches any string segment in the URL. An aspect is what gives that
placeholder meaning: it translates between the raw internal value (typically a
UID) used by Extbase and the human-readable segment that appears in the URL.
Aspects are defined at enhancer level under the
aspects key, keyed by the
placeholder name they apply to.
See also
- Routing aspects — full reference —
all aspect types including
LocaleModifierand custom mapper implementations.
PersistedAliasMapper
The most common aspect for Extbase plugins, implemented by
\TYPO3\. It looks up a
database record by its slug field to resolve a URL segment to a UID, and vice
versa when generating a URL.
routeEnhancers:
ConferencesPlugin:
type: Extbase
limitToPages:
- 'page["module"] == "conferences"'
extension: MyExtension
plugin: Conferences
defaultController: 'Conference::show'
routes:
- routePath: '/{conference_slug}'
_controller: 'Conference::show'
_arguments:
conference_slug: conference
aspects:
conference_slug:
type: PersistedAliasMapper
tableName: tx_myextension_domain_model_conference
routeFieldName: slug
routeValuePrefix: '/'
tableName - The database table that holds the records — typically the Extbase domain
model table (
tx_).{extension}_ domain_ model_ {name} routeField Name - The field whose value is used as the URL segment. This should be a TCA type slug field so that values are guaranteed to be unique and URL-safe. Using a plain title field is possible but risky: special characters are not sanitised automatically, and duplicates cause resolution failures.
routeValue Prefix - Slug fields in TCA store values with a leading
/(for example/typo3camp-). Set2025 routeto strip that prefix from the URL segment. Omit it for non-slug fields.Value Prefix: '/'
When TYPO3 receives /conferences/, the mapper looks up the
record with slug = '/ in the table and passes its UID to
the action as the
conference argument. When generating a URL for a
conference with UID 42, it reads the slug field and inserts the value into the
URL — no UID ever appears in the address bar.
PersistedPatternMapper
Implemented by
\TYPO3\,
this combines multiple database fields into one URL segment. Useful when no slug
field exists and adding one is not an option — for example when extending a
third-party table.
aspects:
conference_slug:
type: PersistedPatternMapper
tableName: tx_myextension_domain_model_conference
routeFieldPattern: '^(?P<title>.+)-(?P<uid>\d+)$'
routeFieldResult: '{title}-{uid}'
routeField Pattern - A regular expression with named capture groups that matches the stored field value.
routeField Result - The template for the URL segment, using the named groups from
route. Appending the UID (Field Pattern {title}-) guarantees uniqueness even when titles are not unique.{uid}
The
Persisted is preferred
whenever a slug field is available — it is simpler and its output is cleaner.
Use
Persisted when
you need to construct the URL segment from multiple fields or when upgrading
from a realurl-era configuration that used title-plus-UID URLs.
See also
StaticValueMapper
Implemented by
\TYPO3\, this maps
a fixed set of values between their internal representation and a human-readable
URL segment. Suitable for arguments that can only take a known list of values —
status flags, type identifiers, named steps in a wizard.
routeEnhancers:
ConferencesPlugin:
type: Extbase
limitToPages:
- 'page["module"] == "conferences"'
extension: MyExtension
plugin: Conferences
defaultController: 'Conference::list'
routes:
- routePath: '/status/{status}'
_controller: 'Conference::list'
aspects:
status:
type: StaticValueMapper
map:
upcoming: 1
running: 2
past: 3
The
map keys are the URL segments; the values are what Extbase receives
as the argument. A request to /conferences/ passes
1
to the action. A URL generated for status
3 produces
/conferences/.
Because the full set of valid values is known, TYPO3 treats the parameter as
static and omits cHash from the generated URL.
For multi-language sites, add a
locale to vary the URL segments per
language without changing the internal values:
aspects:
status:
type: StaticValueMapper
map:
upcoming: 1
running: 2
past: 3
localeMap:
- locale: 'de_DE.*'
map:
bevorstehend: 1
laufend: 2
vergangen: 3
See also
StaticRangeMapper
Implemented by
\TYPO3\, this
declares that a placeholder accepts an integer within a fixed range. The
primary use case is pagination. Unlike a bare \d+ requirement, a
Static marks the parameter
as static, which eliminates cHash from paginated URLs.
aspects:
page:
type: StaticRangeMapper
start: '1'
end: '100'
Set
end to the maximum sensible value for your use case. The example uses
100 pages; TYPO3 enforces a hard upper limit of 1000. Requests with a value
outside the configured range do not match the route — TYPO3 returns a 404
rather than silently passing through an out-of-range value.
See also
Aspects take precedence over requirements
If a placeholder has both a
requirements entry and an
aspects entry, the aspect wins — the
requirements regex is
ignored for that placeholder.
The aspect defines all valid values implicitly, so an additional regex
constraint would be redundant and is silently discarded.
With aspects configured, the next step is generating URLs from controller actions and Fluid templates — see Generating URLs with the UriBuilder.