Skip to main content

How To: Route Enhancer For News

Thanks to Steffen from Helios IT for sharing!

Human Readable URLs are nowadays a TYPO3 core feature and are configured with the new Site Configuration. While it's working nicely for standard page URLs, there are some adjustments needed for extbase extensions like ext:news. In this short article we’ll have a look at that specific part of configuration and we’ll show you how to create a nice and readable URL for your news section.

First of all, we assume that you already have a page tree with some pages and a complete news setup with at least a List view on one page, a Detail view on another and some news articles. You also need a Site Configuration, so that the URL on your page is already cleaned up and no longer contains the part .../index.php?id=1234. If you need some advice for that have a look at the documentation.

With that done, we need to configure the config.yaml file to insert our adjustments for ext:news. This activity has not yet an interface, but you can include that directly into the configuration file. Usually the file should be located at docroot/config or inside typo3conf, this depends on your installation.

/sites/[YourSitesConfiguration]/config.yaml
and there you search for the line routes: {  }. Insert the following lines directly after this. Watch the indents, your code should look like this:

...
routes: {  }
routeEnhancers:
	NewsPages:
		type: Extbase
		# add every page-ID that contains a News Plugin, but not the News Folder. Important: don't use space between the IDs
		limitToPages: [1,2,3...]
		extension: News
		plugin: Pi1
		routes:
			# Detail view
			# example URL given: "/myDetail?tx_news_pi1[action]=detail&tx_news_pi1[controller]=News&tx_news_pi1[news]=2" 
			- { routePath: '/{myNewsTitle}', _controller: 'News::detail', _arguments: {'myNewsTitle': 'news'} }
			# Pagination
			# example URL given: "/myListWithPagination?tx_news_pi1[@widget_0][currentPage]=2"
			- { routePath: '/{myPagination}', _controller: 'News::list', _arguments: {'myPagination': '@widget_0/currentPage'} }
			# DateMenu
			# example URL given: "/myListWithDateMenu?tx_news_pi1[controller]=News&tx_news_pi1[overwriteDemand][month]=12&tx_news_pi1[overwriteDemand][year]=2018"
			# if you want the month first, make it '/{month}/{year}'
			- { routePath: '/{year}/{month}', _controller: 'News::list', _arguments: {'year' : 'overwriteDemand/year', 'month' : 'overwriteDemand/month'} }
		defaultController: 'News::list'
		defaults:
			myPagination: '1'
		requirements:
			myPagination: '\d+'
		aspects:
			# here we get the needed information for a nice URL for _arguments
			myNewsTitle: { type: PersistedAliasMapper, tableName: 'tx_news_domain_model_news', routeFieldName: 'path_segment' }
			myPagination: { type: StaticRangeMapper, start: '1', end: '100' }
			month:
				type: StaticValueMapper
				map:
					# DateMenu => the month for the URL. We assume that German is the default language. The URL will be ".../maerz/2018"
					januar: 1
					februar: 2
					maerz: 3
					april: 4
					mai: 5
					juni: 6
					juli: 7
					august: 8
					september: 9
					oktober: 10
					november: 11
					dezember: 12
				localeMap:
					# If you got more than one language. For the locale go to "Sites Configuration" -> Tab "Languages" -> Locale
					- locale: 'en_EN'
						map:
							# translated month for URL
							january: 1
							february: 2
							march: 3
							april: 4
							may: 5
							june: 6
							july: 7
							august: 8
							september: 9
							october: 10
							november: 11
							december: 12

First of all: save the file and clear the complete cache (Backend -> Maintenance -> Flush Cache). It’s never a bad idea to clear the whole cache after changing the config.yaml.
Now, what has been done so far? Time for some explanations:

With the line limitToPages: [1,2,3...] we’re determining on which page ID we want to add our Route Enhancing. This is mandatory, otherwise nothing would change at all. After that we take care of the routes. For example:

- { routePath: '/{myNewsTitle}', _controller: 'News::detail', _arguments: {'myNewsTitle': 'news'} }

routePath is the URL we’re aiming for in the end. Since this is about the Detail-View we need the _controller set to News::detail. If the routePath has more than one argument you can arrange them in any order you want. For example /{year}/{month} can easily be flipped around if you want the month mentioned first. That would be /{month}/{year}.

Last but not least the _arguments...here we get the necessary configuration from the aspects (we cover that in a few moments).

The _arguments are the part from the URL you want to change e.g. the pagination

.../myListWithPagination?tx_news_pi1[@widget_0][currentPage]=2

With

_arguments {'myPagination': '@widget_0/currentPage'}

you’re telling TYPO3 to grab the @widget... code and put it into myPagination.
After that the aspects come into place and map that information with a simple static range from 1-100. Be advised that it won't work if the URL is not correct. Let's say your URL contains ...&tx_news_pi1[year]=2018 and your _arguments is only {'year' : 'overwriteDemand/year'}. Since you're looking for overwriteDemand in the URL but don't provide it, the _arguments won't match here and nothing will happen.

Now, as mentioned before, the aspects. The most common practice of an aspect is a so-called mapper and currently we’ve got three of them. (StaticRangeMapper, PersistedAliasMapper, PersistedPatternMapper). Check out the changelog for more information and some examples on how to use them. In short, you just replace the given info with fields from the database or just some numbers from 1-100 like in the StaticRangeMapper.

For example the line

myNewsTitle: { type: PersistedAliasMapper, tableName: 'tx_news_domain_model_news', routeFieldName: 'path_segment' }

You can read this like "Go to database-table tx_news_domain_model_news, grab the content from path_segment, map it over the stuff you have in myNewsTitle and show that in the URL". Keep in mind that path_segment is a field specific to ext:news. If you got your own extension you need to adapt it.

But what if something is broken? First of all, always check the indents. That usually fixes 90% of the problems. Also make sure that your limitToPages has no spaces between the IDs. And, as already mentioned, check the correct URL. It's very easy to miss something in the parameters.