Configuring URL rules

The Yii URL router is quite powerful and does two main tasks: it resolves URLs into internal routes and creates URLs from these routes. Router rules description is scattered over the official Yii guide and API docs. Let's try to understand how to configure application rules by example.

Getting ready

  1. Create a fresh Yii application using yiic webapp as described in the official guide (http://www.yiiframework.com/doc/guide/) and find your protected/config/main.php file. It should contain the following:
    // application components
    'components'=>array(
       …
      // uncomment the following to enable URLs in path-format
    'urlManager'=>array(
          'urlFormat'=>'path',
          'rules'=>array(
             '<controller:\w+>/<id:\d+>'=>'<controller>/view',
             '<controller:\w+>/<action:\w+>/<id:\d+>'=>'<controller>/<action>',
             '<controller:\w+>/<action:\w+>'=>'<controller>/<action>',
          ),
       ),
  2. Delete everything from rules as we are going to start from scratch.
  3. In your protected/controllers directory, create WebsiteController.php with the following code inside it:
    class WebsiteController extends CController
    {
       public function actionIndex()
       {
          echo "index";
       }
    
       public function actionPage($alias)
       {
          echo "Page is $alias.";
       }
    }

    This is the application controller that we are going to customize URLs for.

  4. Configure your application server to use clean URLs. If you are using Apache with mod_rewrite and AllowOverride turned on, then you should add the following lines to the .htaccess file under your webroot folder:
    Options +FollowSymLinks
    IndexIgnore */*
    RewriteEngine on
    
    # if a directory or a file exists, use it directly
    RewriteCond %{REQUEST_FILENAME} !-f
    RewriteCond %{REQUEST_FILENAME} !-d
    
    # otherwise forward it to index.php
    RewriteRule . index.php

How to do it...

Our website should display the index page at /home and all other pages at /page/<alias_here>. Additionally, /about should lead to a page with the alias about.

  1. Add the following to your rules in protected/config/main.php:
    'home' => 'website/index',
    '<alias:about>' => 'website/page',
    'page/<alias>' => 'website/page',
  2. After saving your changes, you should be able to browse the following URLs:
    • /home
    • /about
    • /page/about
    • /page/test

The following screenshot shows part of a page that opens when the /about URL is used:

How to do it...

How it works...

Let's review what was done and why it works. We'll start with the rightmost part of the first rule:

'home' => 'website/index',

What is website/index exactly? In the Yii application, each controller and its actions have corresponding internal routes. A format for an internal route is moduleID/controllerID/actionID. For example, the actionPage method of WebsiteController corresponds to the website/page route. So, in order to get the controller ID, you should take its name without the Controller postfix and make its first letter lowercase. To get an action ID, you should take the action method name without the action prefix and, again, make its first letter lowercase.

Now, what is home? To understand it in a better way, we need to know, at least superficially, what's happening when we access our application using different URLs.

When we use /home, the URL router checks our rules one by one starting from the top, trying to match the URL entered with the rule. If the match is found, then the router gets the controller and its action from an internal route assigned to the rule and is executing it. So, /home is the URL pattern that defines which URLs will be processed by the rule it belongs to.

Tip

The fewer rules you have, the fewer checks are needed if the URLs do not match. Fewer URLs means more performance.

There's more...

You can also create parameterized rules using a special syntax. Let's review the third rule:

'page/<alias>' => 'website/page',

Here, we are defining an alias parameter that should be specified in the URL after /page/. It can be virtually anything and it will be passed as the $alias parameter to WebsiteController::actionPage($alias).

You can define a pattern for such a parameter. We did it for the second rule:

'<alias:about>' => 'website/page',

The alias here should match about, otherwise, the rule will not be applied.

See also

  • The Using regular expressions in URL rules recipe
  • The Creating URL rules for static pages recipe
  • The Providing your own URL rules at runtime recipe