---
title: "Routing aspects: mapping route placeholders to URLs"
manual: "TYPO3 Explained"
version: "main"
permalink: "https://docs.typo3.org/permalink/t3coreapi:extbase-routing-aspects@main"
source: "ExtensionArchitecture/Extbase/Routing/Aspects.rst"
rendered: "2026-09-22T15:26:06+00:00"
---

# Routing aspects: mapping route placeholders to URLs {#extbase-routing-aspects}

A route placeholder like `{conference_slug}` 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.

> [!NOTE]
> **See also**
>
> -   [Routing aspects — full reference](https://docs.typo3.org/permalink/t3coreapi:routing-advanced-routing-configuration-aspects@main) —
>     all aspect types including `LocaleModifier` and custom mapper implementations.

## `PersistedAliasMapper` {#extbase-routing-aspects-persisted-alias}

The most common aspect for Extbase plugins, implemented by
`\TYPO3\CMS\Core\Routing\Aspect\PersistedAliasMapper`. 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.

**EXT:my_extension/Configuration/Sets/MyExtension/route-enhancers.yaml**

```yaml
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}`).

-   **`routeFieldName`**

    The field whose value is used as the URL segment. This should be a TCA
    [type slug](https://docs.typo3.org/m/typo3/reference-tca/main/en-us/ColumnsConfig/Type/Slug/Index.html#columns-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.

-   **`routeValuePrefix`**

    Slug fields in TCA store values with a leading `/` (for example
    `/typo3camp-2025`). Set `routeValuePrefix: '/'` to strip that prefix
    from the URL segment. Omit it for non-slug fields.

When TYPO3 receives `/conferences/typo3camp-2025`, the mapper looks up the
record with `slug = '/typo3camp-2025'` 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` {#extbase-routing-aspects-persisted-pattern}

Implemented by `\TYPO3\CMS\Core\Routing\Aspect\PersistedPatternMapper`,
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.

**EXT:my_extension/Configuration/Sets/MyExtension/route-enhancers.yaml**

```yaml
aspects:
  conference_slug:
    type: PersistedPatternMapper
    tableName: tx_myextension_domain_model_conference
    routeFieldPattern: '^(?P<title>.+)-(?P<uid>\d+)$'
    routeFieldResult: '{title}-{uid}'
```

-   **`routeFieldPattern`**

    A regular expression with named capture groups that matches the stored
    field value.

-   **`routeFieldResult`**

    The template for the URL segment, using the named groups from
    `routeFieldPattern`. Appending the UID (`{title}-{uid}`) guarantees
    uniqueness even when titles are not unique.

The `PersistedAliasMapper` is preferred
whenever a slug field is available — it is simpler and its output is cleaner.
Use `PersistedPatternMapper` 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.

> [!NOTE]
> **See also**
>
> [PersistedPatternMapper reference](https://docs.typo3.org/permalink/t3coreapi:routing-aspect-persistedpatternmapper@main)

## `StaticValueMapper` {#extbase-routing-aspects-static-value}

Implemented by `\TYPO3\CMS\Core\Routing\Aspect\StaticValueMapper`, 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.

**EXT:my_extension/Configuration/Sets/MyExtension/route-enhancers.yaml**

```yaml
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/status/upcoming` passes `1`
to the action. A URL generated for status `3` produces
`/conferences/status/past`.

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 `localeMap` to vary the URL segments per
language without changing the internal values:

**EXT:my_extension/Configuration/Sets/MyExtension/route-enhancers.yaml**

```yaml
aspects:
  status:
    type: StaticValueMapper
    map:
      upcoming: 1
      running: 2
      past: 3
    localeMap:
      - locale: 'de_DE.*'
        map:
          bevorstehend: 1
          laufend: 2
          vergangen: 3
```

> [!NOTE]
> **See also**
>
> [StaticValueMapper reference](https://docs.typo3.org/permalink/t3coreapi:routing-aspect-staticvaluemapper@main)

## `StaticRangeMapper` {#extbase-routing-aspects-static-range}

Implemented by `\TYPO3\CMS\Core\Routing\Aspect\StaticRangeMapper`, this
declares that a placeholder accepts an integer within a fixed range. The
primary use case is pagination. Unlike a bare `d+` requirement, a
`StaticRangeMapper` marks the parameter
as static, which eliminates `cHash` from paginated URLs.

**EXT:my_extension/Configuration/Sets/MyExtension/route-enhancers.yaml**

```yaml
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.

> [!NOTE]
> **See also**
>
> [StaticRangeMapper reference](https://docs.typo3.org/permalink/t3coreapi:routing-aspect-staticrangemapper@main)

## Handling deleted or hidden records {#extbase-routing-aspects-fallback}

When a `PersistedAliasMapper` cannot
resolve a slug — because the record has been deleted, hidden, or its slug
changed — TYPO3 returns a 404 by default. The `fallbackValue` property
changes this behaviour.

**EXT:my_extension/Configuration/Sets/MyExtension/route-enhancers.yaml**

```yaml
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
        # null removes the argument from the route result entirely;
        # the action receives null and can redirect to the list
        fallbackValue: null

```

`fallbackValue: null` removes the argument from the route result entirely.
The action receives `null` for that argument instead of a 404. Declare the
action parameter as nullable and handle it explicitly — for example by
redirecting to the list with a flash message:

**EXT:my_extension/Classes/Controller/ConferenceController.php**

```php
<?php

namespace MyVendor\MyExtension\Controller;

use MyVendor\MyExtension\Domain\Model\Conference;
use Psr\Http\Message\ResponseInterface;
use TYPO3\CMS\Core\Type\ContextualFeedbackSeverity;
use TYPO3\CMS\Extbase\Mvc\Controller\ActionController;

class ConferenceController extends ActionController
{
  public function showAction(?Conference $conference = null): ResponseInterface
  {
    if ($conference === null) {
      $this->addFlashMessage(
        'The requested conference could not be found.',
        '',
        ContextualFeedbackSeverity::WARNING,
      );
      return $this->redirect('list');
    }

    $this->view->assign('conference', $conference);
    return $this->htmlResponse();
  }
}

```

A string `fallbackValue` passes that string as the argument value instead,
which lets you show a default record rather than an error page.

> [!NOTE]
> **See also**
>
> [Aspect fallback value handling](https://docs.typo3.org/permalink/t3coreapi:routing-aspect-fallback-handling@main)

## Aspects take precedence over requirements {#extbase-routing-aspects-precedence}

If a placeholder has both a
[requirements](https://docs.typo3.org/permalink/t3coreapi:extbase-routing-routes-requirements@main) 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](https://docs.typo3.org/permalink/t3coreapi:extbase-routing-uri-builder@main).
