5. URL Routing

Now that we understand the directory structure, how are the URLs created to invoke a controller to perform its function?

Let's take an example. In your browser, navigate to your Yii install (Frontend if using Advanced Template). In the top navigation bar that is shown with a default install, click on About.

The URL in your address bar should resemble the following:

http://yiisite.com/index.php?r=site%2Fabout

Notice the query string: r=site%2Fabout

The 'r' refers to routing. The %2F is URL encoding for the symbol '/'. Thus, decoded, it would be rendered: r=site/about

The format for routing is: controller/action

That would mean, for this example, the specified controller is site and the specified action is about .

To decipher what this refers to, lets look at some actual code. In your code editor, navigate to your controllers directory (frontend/controllers for Advanced Template) and open the file SiteController.php.

Notice the class definition:

class SiteController extends Controller

First, take note that the class name matches the file name. The naming convention for controllers is to have the controller name, with first letter capitalized, followed by the word Controller, also first letter capitalized (camel case). Thus, the name of this controller is 'site'. This matches the pre-slash part of site/about. Therefore, site/about invokes the controller SiteController.

Now take note of the post-slash portion of site/about. In this case, it is the word 'about'. This specifies the action to call inside of the controller. If you look farther down the script, you will see a function defined as such:

public function actionAbout()
{
    return $this->render('about');
}

By convention, all action functions are named using the word 'action' all lowercase, followed by the name of the action with the first letter uppercase. Thus, the route site/about invokes the function actionAbout().

5.1 Default Controller and Action

What controller and action is invoked when you navigate to the root url, in our case http://yiisite.com, with no query string parameters?

In such a case, the default controller and action will be called. By default, the default controller is SiteController and the default action is actionIndex() . Therefore, navigating to http://yiisite.com is the same as navigating to: http://yiisite.com/index.php?r=site%2Findex

Note: as is typical with most web servers, navigating to the root url, http://yiisite.com in this case, defaults to the file named index.php. Thus, it is the equivalent of navigating to http://yiisite.com/index.php .

This behavior can be modified by adjusting the settings in the config file (config/web.php in Basic Template or frontend/config/main.php in Advanced Template to apply to the frontend). If you would like to change the default controller from 'site' to 'foo', you would add the following key/value to the $config[] array:

'defaultRoute' => 'foo'

If this were done, navigating to http://yiisite.com would be equivalent to http://yiisite.com/index.php?r=foo%2Findex and would invoke actionIndex() in the FooController class.

If you desire to change the default action from 'index' to something else, say 'home' as an example, you would do so simply by adding a public property to the class as such:

public $defaultAction = 'home';

Thus, with 'foo' still set as the default controller, navigating to http://yiisite.com would be equivalent to: http://yiisite.com/index.php?r=foo%2Fhome

5.2 Pretty Urls

In practice, using the url format of http://yiisite.com/index.php?r=site%2Fabout is not common nor desirable. It is much more common to see the format: http://yiisite.com/site/about

To make the later equivalent to the former, we need to do two things: 1. Adjust the config file and 2. Install a .htaccess file in document root.

Open the config file config/web.php (common/config/main.php for Advanced Template to apply to both frontend and backend). In the $config[] array, locate the 'components' key, which itself also references an array. In the 'components' array, add the following key/value:

'urlManager' => [
    // Disable index.php
    'showScriptName' => false,
    // Disable r= routes
    'enablePrettyUrl' => true
],

Next, in the document root (the web directory, remembering there is a separate web directory for both frontend and backend if using Advanced Template), create the following file and name it: .htaccess (This is assuming you are using Apache as your web server.)

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
			

The Magic Dash

What if you have an action in camel case, such as actionAboutYii? How would you construct the URL to access such?

Simple: The dash!

To access actionAboutYii in controller Site you would use: http://yiisite.com/site/about-yii

In routing, the dash is removed and the following character is changed to upper case.