Tuesday, July 3, 2012

Creating URL rules for static pages in YII framework

A website typically contains some static pages. Usually, they are /about, /contact, /tos,
and so on, and it is common to handle these pages in a single controller action. Let's find a
way to create URL rules for these types of pages

1. Create a fresh Yii application using yiic webapp as described in the official guide
and find your protected/config/main.php. 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, create WebsiteController with the
following code:
class WebsiteController extends CController
{
public function actionPage($alias)
{
echo "Page is $alias.";
}
}
4. Configure your application server to use clean URLs. If you are using Apache with
mod_rewrite and AllowOverride turned on 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
The most straightforward way is defining a rule for each page:
'<alias:about>' => 'website/page',
'<alias:contact>' => 'website/page',
'<alias:tos>' => 'website/page',
Using regular expressions, we can compact it to a single rule:
'<alias:(about|contact|tos)>' => 'website/page',
Now, what if we want the URL to be /tos and an alias parameter to be terms_of_service?
No problem, we can use default parameters to achieve it:
'tos' => array('website/page', 'defaultParams' => array('alias' =>
'terms_of_service')),
OK. What if we have many pages and want to be able to dynamically create pages without
adding more rules or changing existing ones?
We can achieve this with the following rule:
'<alias>' => 'website/page'
As this rule matches everything, we need to place it last, so it won't affect all other rules. In
addition, default rules with one slug, such as controller name will stop working. To overcome
this issue, we need to add default rules which we deleted in the Getting ready section of
this recipe.
How it works...
Let's read rules we just wrote.
'<alias:about>' => 'website/page',
If the URL is /about, then pass it as the alias parameter to website/page.
'<alias:(about|contact|tos)>' => 'website/page',
If the URL is /about or /contact or /tos, then pass it as the alias parameter to
website/page.
'tos' => array('website/page', 'defaultParams' => array('alias' =>
'terms_of_service')),
When the URL is /tos, pass terms_of_service as the alias parameter value.

This rule is a bit special because it uses default parameter option. Default parameter allows
you to set a value that will be used if parameter with name specified is omitted. When you
need to specify an option for the rule, you should use an array notation:
'pattern' => array('internal/route', 'option' => 'value', 'option' =>
'value', …),

No comments:

Post a Comment