Use Routing to rewrite URLs
This section will show you how you can rewrite the URLs for news using Routing Enhancers and Aspects. TYPO3 Explained has a chapter Introduction to routing that you can read if you are not familiar with the concept yet. You will no longer need third party extensions like RealURL or CoolUri to rewrite and beautify your URLs.
Quick start
This section explains in short how to rewrite the URLs for the detail page in a project where there is only one detail view page on the whole site and where rewriting of things like pagination is not desired or needed.
Open the configuration of the site. You should find it at
/config/
.
At the bottom of the file include the following:
routeEnhancers:
News:
type: Extbase
limitToPages:
- <uid of single page>
extension: News
plugin: Pi1
routes:
- routePath: '/{news-title}'
_controller: 'News::detail'
_arguments:
news-title: news
aspects:
news-title:
type: NewsTitle
Save the file, delete all caches and try it out
Troubleshooting
- Did you save the site configuration file?
- Did you delete all caches?
- In the format YAML indentation matters. The code above must be indentated exactly
as shown, the keyword
route
must not be indeted.Enhancers - The configuration above is limited to only one page containing a single view of news. Did you put the correct pid of page containing the news plugin displaying single news?
Detailed explaination and advanced use cases
How to rewrite URLs with news parameters
On setting up your page you should already have created a site configuration. You can do this in the backend module Site Managements > Sites.
Your site configuration will be stored in
/config/
. The following
configurations have to be applied to this file.
Any URL parameters can be rewritten with the Routing Enhancers and Aspects.
These are added manually in the config.
:
- Add a section
route
, if one does not already exist.Enhancers - Choose an unique identifier for your Routing Enhancer. It doesn't have to match any extension key.
type
: For news, the Extbase Plugin Enhancer (Extbase
) is used.extension
: the extension key, converted toUpper
.Camel Case plugin
: the plugin name of news is just Pi1.- After that you will configure individual routes and aspects depending on your use case.
routeEnhancers:
News:
type: Extbase
extension: News
plugin: Pi1
# routes and aspects will follow here
Tip
If your routing doesn't work as expected, check the indentation of your configuration blocks. Proper indentation is crucial in YAML.
Using limitToPages
It is recommended to limit route
to the pages where they are needed.
This will speed up performance for building page routes of all other pages.
routeEnhancers:
News:
type: Extbase
limitToPages:
- 8
- 10
- 11
extension: News
plugin: Pi1
# routes and aspects will follow here
Warning
Not setting the limit
parameter may lead to unwanted side effects, e. g. not working error handling!
Multiple routeEnhancers for news
If you use the news extension for different purposes on the same website (for example news and events), you may want different URL paths for them (for example /article/ and /event/). It is possible to configure more than one routing enhancer for the news plugin on the same website.
Use limit
to assign the appropriate configuration to the
desired pages.
routeEnhancers:
News:
type: Extbase
limitToPages:
- 8
- 10
- 11
extension: News
plugin: Pi1
# etc.
NewsEvents:
type: Extbase
limitToPages:
- 17
- 18
extension: News
plugin: Pi1
# etc.
About routes and aspects
In a nutshell:
routes
will extend an existing route (means: your domain and page- path) with arguments from GET parameters, like the following controller/action pair of the news detail view.
aspects
can be used to modify these arguments. You could for- example map the title (or better: the optimized path segment) of the current news. Different types of Mappers and Modifiers are available, depending on the case.
- URL of detail page without routing:
https://www.example.com/news/detail?tx_news_pi1[action]=detail&tx_news_pi1[controller]=News&tx_news_pi1[news]=5&cHash=
- URL of detail page with routes:
https://www.example.com/news/detail/5?cHash=
- URL of detail page with routes and aspects:
https://www.example.com/news/detail/title-of-news-article
The following example will only provide routing for the detail view:
routeEnhancers:
News:
type: Extbase
extension: News
plugin: Pi1
routes:
- routePath: '/{news-title}'
_controller: 'News::detail'
_arguments:
news-title: news
aspects:
news:
type: NewsTitle
Please note the placeholder {news-
:
- First, you assign the value of the news parameter (
tx_
) innews_ pi1 [news] _arguments
. - Next, in
route
you add it to the existing route.Path - Last, you use
aspects
to map thepath_
of the given argument.segment
Both routes and aspects are only available within the current Routing Enhancer.
The names of placeholders are freely selectable.
Common routeEnhancer configurations
Basic setup (including categories, tags and the RSS/Atom feed)
Prerequisites:
The plugins for List View and Detail View are on separate pages.
If you use the Category Menu or Tag List plugins to filter news records, their titles (slugs) are used.
The order of the config does matter! If you want to have categories+pagination, that configuration has to stand before the part for categpries alone
Result:
- Detail view:
https://www.example.com/news/detail/the-news-title
- Pagination:
https://www.example.com/news/page-2
- Category filter:
https://www.example.com/news/my-category
- Category filter + pagination:
https://www.example.com/news/my-category/page-2
- Tag filter:
https://www.example.com/news/my-tag
- Tag filter + pagination:
https://www.example.com/news/my-tag/page-2
routeEnhancers:
News:
type: Extbase
extension: News
plugin: Pi1
routes:
- routePath: '/'
_controller: 'News::list'
# Pagination
- routePath: '/page-{page}'
_controller: 'News::list'
_arguments:
page: 'currentPage'
# Category + pagination:
- routePath: '/{category-name}/page-{page}'
_controller: 'News::list'
_arguments:
category-name: overwriteDemand/categories
page: 'currentPage'
# Category
- routePath: '/{category-name}'
_controller: 'News::list'
_arguments:
category-name: overwriteDemand/categories
# Tagname + pagination
- routePath: '/{tag-name}/page-{page}'
_controller: 'News::list'
_arguments:
tag-name: overwriteDemand/tags
page: 'currentPage'
# Tagname
- routePath: '/{tag-name}'
_controller: 'News::list'
_arguments:
tag-name: overwriteDemand/tags
# Detail
- routePath: '/{news-title}'
_controller: 'News::detail'
_arguments:
news-title: news
defaultController: 'News::list'
defaults:
page: '0'
aspects:
news:
type: NewsTitle
page:
type: StaticRangeMapper
start: '1'
end: '100'
category-name:
type: NewsCategory
tag-name:
type: NewsTag
PageTypeSuffix:
type: PageType
map:
'feed.xml': 9818
'calendar.ical': 9819
Tip
If you are using the routing for pagination, be sure it is in the code before the configuration for the detail view! Otherwise you can run into trouble on pages with plugin view "List articles with detail view".
Localized pagination
Prerequisites:
The website provides several frontend languages.
Result:
- English:
https://www.example.com/news/page-2
- Danish:
https://www.example.com/da/news/side-2
- German:
https://www.example.com/de/news/seite-2
routeEnhancers:
News:
type: Extbase
extension: News
plugin: Pi1
routes:
- routePath: '/{page-label}-{page}'
_controller: 'News::list'
_arguments: {'page': 'currentPage'}
defaultController: 'News::list'
defaults:
page: ''
requirements:
page: '\d+'
aspects:
page:
type: StaticRangeMapper
start: '1'
end: '100'
page-label:
type: LocaleModifier
default: 'page'
localeMap:
- locale: 'da_DK.*'
value: 'side'
- locale: 'de_DE.*'
value: 'seite'
Explanation:
The Locale
aspect type will set a default value for the
English language.
You're then able to add as many locale
configurations as you
need for the page translations of your website.
The value of locale
refers to the value in your site configuration.
Human readable dates
Prerequisites:
For List View with a Date Menu plugin, to filter by date. Also includes configuration for the pagination.
Result:
https://www.example.com/news/2018/march
https://www.example.com/news/2018/march/page-2
routeEnhancers:
DateMenu:
type: Extbase
extension: News
plugin: Pi1
routes:
# Date year/month + pagination:
- routePath: '/{date-year}/{date-month}/page-{page}'
_controller: 'News::list'
_arguments:
date-month: 'overwriteDemand/month'
date-year: 'overwriteDemand/year'
page: 'currentPage'
# Date year/month:
- routePath: '/{date-year}/{date-month}'
_controller: 'News::list'
_arguments:
date-month: 'overwriteDemand/month'
date-year: 'overwriteDemand/year'
page: 'currentPage'
# Date year + pagination:
- routePath: '/{date-year}/page-{page}'
_controller: 'News::list'
_arguments:
date-year: 'overwriteDemand/year'
page: 'currentPage'
# Date year:
- routePath: '/{date-year}'
_controller: 'News::list'
_arguments:
date-month: 'overwriteDemand/month'
date-year: 'overwriteDemand/year'
page: 'currentPage'
# Pagination:
- routePath: '/'
_controller: 'News::list'
- routePath: '/page-{page}'
_controller: 'News::list'
_arguments:
page: 'currentPage'
- routePath: '/{news-title}'
_controller: 'News::detail'
_arguments:
news-title: news
defaultController: 'News::list'
defaults:
page: '0'
date-month: ''
date-year: ''
requirements:
date-month: '\d+'
date-year: '\d+'
page: '\d+'
aspects:
news:
type: NewsTitle
page:
type: StaticRangeMapper
start: '1'
end: '25'
date-month:
type: StaticValueMapper
map:
january: '01'
february: '02'
march: '03'
april: '04'
may: '05'
june: '06'
july: '07'
august: '08'
september: '09'
october: '10'
november: '11'
december: '12'
date-year:
type: StaticRangeMapper
start: '2000'
end: '2030'
Explanation:
You will need a new route
for every possible combination of
arguments (pagination, month with/without pagination, ...).
Potential errors:
If you want 2018/
but get 2018/
instead, compare your
Static
for months with your date arguments.
Are you using different date formats (with/without leading zeros)?
You can either remove the leading zero in your aspects
or adapt the
TypoScript setting:
plugin.tx_news.settings.link {
hrDate = 1
hrDate {
day = j
// 'n' for 1 through 12. 'm' for 01 through 12.
month = m
year = Y
}
}
You can configure each argument (day/month/year) separately by using the configuration of PHP function date.
Warning
Using the Static
is strictly limited to 1000 items per
a single range and 10000 items per routing enhancer.
That means you'll have to multiply all possible combinations in a routing enhancer, for example:
12 months × 30 years (2000-2030) × 25 pages (pagination) = 9000 possible items
If you exceed this limit, you'll either have to build a custom and more
specific mapper, or reduce the range in one of your Static
.
How to create URLs in PHP
The following snippet is a good example how an URL can be generated properly
protected function generateUrl(SiteInterface $site, int $recordId, int $detailPageId): string
{
$additionalQueryParams = [
'tx_news_pi1' => [
'action' => 'detail',
'controller' => 'News',
'news' => $recordId
]
];
return (string)$site->getRouter()->generateUri(
(string)$detailPageId,
$additionalQueryParams
);
}