URIs with German special characters do not work (404 error) in Zend Framework 2

I want to get a list of cities in which the name of each city is indicated, and links to a page for this city:

enter image description here

The links (created in the script view) are as follows:

http://project.loc/catalog/Berlin (in the HTML source code url-encoded: Berlin) http://project.loc/catalog/Erlangen (in the HTML source code url-encoded: Erlangen) http://project.loc/catalog/Nürnberg (in the HTML source code url-encoded: N%C3%BCrnberg) 

"Berlin", "Erlangen", etc., but if the city name contains a German special character ( ä , ö , ü , Ä , Ö , Ü , or ß ), like "Nuremberg", error 404 occurs:

Error 404 Page not found. The requested URL cannot be matched by routing. There are no exceptions.

Why? And how to do it?

Thanks in advance!

EDIT:

My router settings:

 'router' => array( 'routes' => array( 'catalog' => array( 'type' => 'literal', 'options' => array( 'route' => '/catalog', 'defaults' => array( 'controller' => 'Catalog\Controller\Catalog', 'action' => 'list-cities', ), ), 'may_terminate' => true, 'child_routes' => array( 'city' => array( 'type' => 'segment', 'options' => array( 'route' => '/:city', 'constraints' => array( 'city' => '[a-zA-ZäöüÄÖÜß0-9_-]*', ), 'defaults' => array( 'controller' => 'Catalog\Controller\Catalog', 'action' => 'list-sports', ), ), 'may_terminate' => true, 'child_routes' => array( // ... ), ), ), ), ), ), 
+2
source share
1 answer

You need to change your restrictions, you can use a regular expression that will match UTF8 characters, something like this:

 '/[\p{L}]+/u' 

Note the / u (unicode) modifier.

EDIT:

The problem is resolved .

Explanation:

A RegEx route binds a URI using preg_match(...) (line 116 or 118 Zend \ Mvc \ Router \ Http \ Regex). To process a string with "special characters" (128+), you need to go through the template modifier u to preg_match(...) . Like this:

 $thisRegex = '/catalog/(?<city>[\p{L}]*)'; $regexStr = '(^' . $thisRegex . '$)u'; // <-- here $path = '/catalog/Nürnberg'; $matches = array(); preg_match($regexStr, $path, $matches); 

And since RegEx Route passes the string with the url-enccoded number to preg_match(...) , then it should be needed to decode the first line:

 $thisRegex = '/catalog/(?<city>[\p{L}]*)'; $regexStr = '(^' . $thisRegex . '$)u'; $path = rawurldecode('/catalog/N%C3%BCrnberg'); $matches = array(); preg_match($regexStr, $path, $matches); 

These two steps are not provided in the RegEx route, so preg_match(...) gets a rotation like '/catalog/N%C3%BCrnberg' and tries to translate it into a regular expression, for example '/catalog/(?<city>[\\p{L}]*)/u'

the solution is to use the RegEx custom route. Here is an example.

+3
source

All Articles