Yii 1.1: How to ensure unicity to url

17 followers

Ensure uniciy to url

Many time for SEO porpouses is important that each page will have a unique address.

If, for example, we have a rule like:

'post/<id:\d+>'=>'post/read',

This url will be valid:

post/read/id/5
post/read?id=5
post/5

If we have a suffix, for example .html, also this url will be available:

post/read/id/5.html
post/read.html?id=5
post/5.html

A total of 6 url, that is not seo compliant.

The solution is quite simple, just write this in your controller:

public function beforeAction($action)
{
    $normalizedUrl = CHtml::normalizeUrl(array_merge(array("/".$this->route), $_GET));
    if (Yii::app()->request->url != $normalizedUrl && strpos($normalizedUrl, Yii::app()->errorHandler->errorAction) === false) {
        $this->redirect($normalizedUrl, true, 301);
    }
 
    return parent::beforeAction($action);
}

This will redirect all alternative url to the one 'legal'. Using 301 instead 302 will make the browser (and, we hope, google bots) aware that the correct address is another one.

You can implement a master class for semplicity:

<?php
/**
 * BlockController is a customized base controller class.
 * All controller classes with unique url  should extend from this base class.
 */
class BlockController extends Controller
{
    public function beforeAction($action)
    {
        $normalizedUrl = CHtml::normalizeUrl(array_merge(array("/".$this->route), $_GET));
        if (Yii::app()->request->url != $normalizedUrl && strpos($normalizedUrl, Yii::app()->errorHandler->errorAction) === false) {
            $this->redirect($normalizedUrl, true, 301);
        }
 
        return parent::beforeAction($action);
    }
}

Notice that you cannot add this rule for actionError and actionIndex, so if you want to make unique addresses in the site controller you cannot extend the master controller, but you have to implement a special method with exception for this two actions.

Links

Total 3 comments

#6097 report it
marcovtwout at 2011/12/12 10:38am
Exception for error handler

You don't want to redirect when Yii is calling the error handler:

$normalizedUrl = CHtml::normalizeUrl(array_merge(array("/".$this->route), $_GET));
        if (Yii::app()->request->url != $normalizedUrl && strpos($normalizedUrl, Yii::app()->errorHandler->errorAction) === false) {
            $this->redirect($normalizedUrl, true, 301);
        }
#5052 report it
redguy at 2011/09/10 09:45am
nice, but does not work as expected...

Have found that this works:

$url = array_merge( array( "/" . $this->route ), $_GET );
if( Yii::app()->request->url != CHtml::normalizeUrl( $url ) ) {
     $this->redirect( $url, true, 301 );
}

Most important is "/" (slash) prepended to route as controller can be placed in module and in such case your code throws error.

#4674 report it
Y!! at 2011/08/03 05:07am
Strict parsing

One can enable CUrlManager::useStrictParsing to disallow such url variations.

Leave a comment

Please to leave your comment.

Write new article
  • Written by: zaccaria
  • Updated by: marcovtwout
  • Category: Tips
  • Yii Version: 1.1
  • Votes: +14
  • Viewed: 10,803 times
  • Created on: Jul 26, 2011
  • Last updated: Dec 12, 2011
  • Tags: SEO, unique, URL