Best place to handle url slugs

Hi guys!

I’m in the painful process to convert a Drupal site on Yii. Here’s the scenario i need help with at the moment:

I need to handle invalid URLs such as, without throwing 404 error. I need to take the request uri from this, lookup into a DB table url_alias, and depending upon that need to forward it either one of some specified controllers such as nodes, terms, users etc…

Below is the Controller::nodeRouter() method for decision logic. Question is what’s the best place to place this conditional logic ? This nodeRouter shall only be triggered if the url/route is invalid but without throwing the 404 exception.

    public static function nodeRouter($urlpath=null) {

     $urlpath = $urlpath ? $urlpath : Yii::app()->request->pathInfo; 

      // Handle Root/Home Page

	    if (empty($urlpath)) {



      $sqlAlias = "SELECT * FROM ".TBL_URL_ALIASES." WHERE alias='$urlpath'";

      $modelAlias = Yii::app()->db->createCommand($sqlAlias)->queryAll();

      $modelAlias = isset($modelAlias[0]) ? $modelAlias[0] : array();

      if (isset($modelAlias['id'])) {

    $route_controller_array = explode("/",$modelAlias['path']);

    $route_controller = $route_controller_array[0];    returns one of these:   nodes,  terms,  users   

    $route_id = $route_controller_array[1];            returns records pk id i.e.  44 or something


    switch ($route_controller) {

      case 'nodes':

        $_GET['id'] = $route_id;




      case 'terms':

        $_GET['id'] = $route_id;



      case 'users':







      // If not routed any where means the Request is invalid

      return false;



I tried placing Controller::nodeRouter() in the following places:

Placement 1:


In Controller::init() - Here i get an infinite loop as Controller::init() triggers each time after Controller::forward() is fired.

Placement 2:


In SiteController::actionError() - All works fine here except the issue that the desired pages are rendered but with a 404 Exception. I understand this exception comes from CWebApplication::runController(). This ugly solution will create major SEO issues for the site and i can’t go with that. Neither do i want to hack the core.

How exactly shall i get around with this issue. Appreciate if i can get some help.



Friends, welcome your suggestions on this. In the meanwhile i’ve hacked the core a little bit to move forward. If this helps someone.

We have a method available in Yii named CController::missingAction() to do something with the request if the controller is valid but the requested action in URL is invalid.

I’ve wrote a similar method named missingController() which catches all the invalid requests and give you a chance to do something with them before throwing the 404 Exception.

Here’s how i did this:


  • Open protected/components/Controller.php

  • Add the following method to this file:

    public static function missingController($route) {

      // My additional routing logic is this, you may add your own logic here

      $valid = Controller::nodeRouter();  // See above for the contents of this method.

      if (!$valid) {

        return true;    // Returning true here means you want to throw 404 error




  • Open yii/framework/web/CWebApplication.php

  • Change the method runController($route) as follows:

public function runController($route)











else {

  // Raised an Event to run our own logic before throwing 404. 

	$missingController = Controller::missingController($route);

  if ($missingController) {

    throw new CHttpException(404,Yii::t('yii','Unable to resolve the request "{route}".',





modifying framework files is highly discouraged… instead you should create your own class that is extending CWebApplication and create instance of this class in index.php instead of default CWebApplication:

I agree we should not modify the core and extending CWebApplication is the correct way. Thanks!