I've been searching all around Stackoverflow and YII forums, there are many answers, which didn't help me...

This is my case.

I have controller called: proj and an action called view. It gets: id(int), name(string).

The desired name gets sometimes with special chars such as: [+,!#$%^&*-]

So when I'm running createUrl() function it returns me not so friendly url.

For example: http://www.qa-mysite.com/proj/1029/Conservation+of+the+Vermont+Salt+Pan+System%2C+Hermanus%2C+South+Africa.

id = 1029 name = Conservation of the Vermont SaltPan System, Hermanus, South Africa.

I want the result to be: http://www.qa-mysite.com/proj/1029/conservation-of-the-vermont-salt-pan-system-hermanus-south-Africa

So actually i need to strip the special chars and change the delimiter between spaces to "-" instead of "+".

My current configurations of the curlManager are:

'urlManager'=>array(
            'urlFormat'=>'path',
            'showScriptName'=>false,
            'appendParams' => true,
            'rules'=>array(
            //array('proj/view/<name:\w+>', 'pattern'=>'proj/<id:\d+>'),
                //'<controller:\w+>/<id:\d+>'=>'<controller>/view',
                'proj/<id:\d+>/<name:\w+>'=>array('proj/view', 'caseSensitive'=>false),
                '<controller>/<id:\d+>/<name:.*?>'=>'<controller>/view',
                '<controller:\w+>/<action:\w+>/<id:\d+>'=>'<controller>/<action>',
                '<controller:\w+>/<action:\w+>'=>'<controller>/<action>',
            ),
        )

CreateUrl example:

$this->createUrl('proj/view', array('id' => $data->id, 'name' => $data->name));

After the urls will be changed I need to do 301 redirects of the old ones to the new-seo-friendly urls.

Note: I cannot do hardcoded str_replace.

Many thanks for any help :]

有帮助吗?

解决方案

Create your own url manager by subclassing CUrlManager and ovveride createUrl a bit, in example:

class MyUrlManager extends CUrlManager {
    public function createUrl($route,$params=array(),$ampersand='&') {
        if($route == 'proj/view' && isset($params['name'])) {
            $params['name'] = processYourParamFunction($params['name']);
        }
        return parent::createUrl($route,$params,$ampersand);
    }
}

Then modify your config to use this class:

...
'urlManager' => [
    'class' => 'MyUrlManager'
...
]

It is one of great Yii features, natural inversion of control:)

For second part of question:

In you view action simply redirect to new url with createurl if you detect unwanted characters . Just make sure you not hit redirect loop.

Update:

To redirect with 301 just pass redirect code a third param to redirect call:

$this->redirect('route', true, 301);

Side note:

Use cannonical to point search engines to proper url

其他提示

First of all PeterM's answer is a good one, It's a nice approach.

I've did it in a different way.

I've created helper called "TextHelper", with one static function:

class TextHelper{
    public static function cleanText($text=""){
        $text = preg_replace('/[^A-Z0-9]+/i', '-', $text);
        $text = strtolower(trim($text, '-'));

        return $text;
    }
}

And changed the createUrl() to get cleaned by the cleanText(), like this:

$this->createUrl('proj/view', array('id' => $proj->id, 'name' => TextHelper::getSlug($proj->name)));

For last, my config/main.php:

'urlManager'=>array(
            'urlFormat'=>'path',
            'showScriptName'=>false,
            'appendParams' => true,
            'rules'=>array(
                'proj/<id:\d+>/<name:\w+>'=>array('proj/view', 'caseSensitive'=>false),
                '<controller>/<id:\d+>/<name:.*?>'=>'<controller>/view',
                '<controller:\w+>/<action:\w+>/<id:\d+>'=>'<controller>/<action>',
                '<controller:\w+>/<action:\w+>'=>'<controller>/<action>',
            ),
        )

That solution did the job for me. Hope it will be easy and efficient solution for other developers which need to face this problem.

That solution did the job for me. Hope it will be easy and efficient solution for other developers which need to face this problem.

'urlManager'=>array(
                'urlFormat'=>'path',
                'showScriptName'=>false,
                'appendParams' => true,
                'rules'=>array(
                    'proj/<id:\d+>/<name:\w+>'=>array('proj/view', 'caseSensitive'=>false),
                    '<controller>/<id:\d+>/<name:.*?>'=>'<controller>/view',
                    '<controller:\w+>/<action:\w+>/<id:\d+>'=>'<controller>/<action>',
                    '<controller:\w+>/<action:\w+>'=>'<controller>/<action>',
                ),
            )
许可以下: CC-BY-SA归因
不隶属于 StackOverflow
scroll top