Hyphenation of routes in URL management

You are viewing revision #1 of this wiki article.
This is the latest version of this article.

In this article, we introduce an approach that allows automatic hyphenation of the route part in URLs.

As we know, Yii uses the URL manager to support URL creation and parsing. However, the default implementation does not deal well with the route that has mixed cases. For example, given a route /createAccount, the URL manager would generate the following URL by default:

/user/createAccount

For SEO purists, this is not very pretty. They would want something like /user/create-account for better readability. To achieve this goal, we can add the following rule when configuring the URL manager:

'user/create-account' => 'user/createAccount'

This is fine but not perfect, because it requires us to specify a similar rule for every route that has mixed cases. To avoid this trouble and also to improve the performance, we can extend [CUrlManager] as follows,

class UrlManager extends CUrlManager
{
	public $showScriptName = false;
	public $appendParams = false;
	public $useStrictParsing = true;
	public $urlSuffix = '/';

	public function createUrl($route, $params = array(), $ampersand = '&')
	{
		$route = preg_replace_callback('/(?<![A-Z])[A-Z]/', function($matches) {
			return '-' . lcfirst($matches[0]);
		}, $route);
		return parent::createUrl($route, $params, $ampersand);
	}

	public function parseUrl($request)
	{
		$route = parent::parseUrl($request);
		return lcfirst(str_replace(' ', '', ucwords(str_replace('-', ' ', $route))));
	}
}

In the above, we define a new class UrlManager which extends from [CUrlManager]. We mainly override the createUrl() and parseUrl() methods to perform the hyphenation of routes. We also override the default values of several properties of [CUrlManager] so that the URLs are even more SEO friendly.

Now we need to make some minor changes to the application configuration:

return array(
	// ....
	'components' => array(
		'urlManager' => array(
			'class' => 'UrlManager',
			'rules' => array(
				// ....
				'<controller:[\w\-]+>/<action:[\w\-]+>' => '<controller>/<action>',			
			),
		),
	),
);

In the above, we mainly specify the class of urlManager to be our new class UrlManager. We also change the rule a little bit so that it can match the hyphens (-) in the URLs (the default setting only matches word characters which don't include hyphens).

With these code in place, for the route user/createAccount we would obtain URL /user/create-account/. The ending slash is because we set urlSuffix to be / in UrlManager.

Note: Because the above code uses anonymous function and lcfirst(), it requires PHP 5.3 or above.