根据参数值Yii重写路径

I have several rules in Yii that allows me to rewrite some routes, where every will be pass to the action as a get parameter.

'<department>' => 'products/index',
'<department>/<category>' => 'products/index',

I want to explicitly write a rule that depending of the parameter value will change the url to whatever I want

example, right now I have an URL like this www.mysite.com/Books+%26+Pencils which was rewritten because of this rule '<department>' => 'products/index', which is ok

I want to change that URL to www.mysite.com/books-pencils , if anyone know how to write a rule that compares the value of the deparment attribute and then rewrites it to whatever I want.

THanks

You can use a custom class to handle you special requests. I have used sth like this, to get my custom URLs out of a database:

 'urlManager'=>array(
            'rules'=>array(
                array(
                    'class' => 'application.components.UrlRule',
                ),
            ),
        ),

Then you create your custo class similar to this:

<?php

Yii::import("CBaseRule");

class UrlRule extends CBaseUrlRule
{
    public function createUrl($manager,$route,$params,$ampersand)
    {
        // check for my special case of URL route, if not found, then return the unchaged route
        preg_match("/^(.+)\/(.+)$/", $route, $r);
        if(!is_array($r) or !isset($r[1]) or !isset($r[2])) {
            return $route;
        }

        // handle your own route request, and create your url
        $url = 'my-own-url/some-thing';

        // check for any params, which i also want to add
        $urlParams = $manager->createPathInfo($params,"=","&");

        $return = trim($url,'/');
        $return.= $urlParams ? "?" . $urlParams : "";

        return $return;
    }

    public function parseUrl($manager,$request,$pathInfo,$rawPathInfo)
    {

        // handle my special url request
        $controller = '....';
        $action = '.....';

        // return the controller/action that should be used     
        return lcfirst($controller)."/".$action;
    }
}

I do not know if this was what you wanted, but at least in this class you can do everything you need with the URL requested. If you would e.g. like to redirect a lot of similar URLs with a 301 Redirect to 1 URL, you could think of sth like this in the parseUrl function

// check my route and params, and if I need to redirect
$request->redirect('/your/new/url/?params=bla',true,'301');

First of all, if you want to change a URL, you should do a redirect (in this case 301). To implement this logic you can use custom URL rule class.

Url manager configuration:

'rules' => array(
    // custom url rule class
    array(
        'class' => 'application.components.MyUrlRule',
    ),
)

MyUrlRule class:

class MyUrlRule extends CBaseUrlRule
{
    public function createUrl($manager,$route,$params,$ampersand)
    {
        // Logic used to create url.
        // If you do not create urls using Yii::app()->createUrl() in your app,
        // you can leave it empty.
    }

    public function parseUrl($manager,$request,$pathInfo,$rawPathInfo)
    {
        // modify url
        $pathInfoCleaned = strtolower(preg_replace('+%26+', '-', $pathInfo));

        // redirect if needed
        if ($pathInfo !== $pathInfoCleaned) {
            $request->redirect($pathInfoCleaned, true, 301);
        }

        // parse params from url
        $params = explode('/', $pathInfo);
        if (isset($params[0])) {
            $_GET['department'] = $params[0];
            if (isset($params[1])) {
                $_GET['category'] = $params[1];
            }
        }

        return 'products/index';
    }
}