3

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 :]

Michael Kisilenko
  • 491
  • 2
  • 6
  • 15

3 Answers3

3

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

3

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.

Michael Kisilenko
  • 491
  • 2
  • 6
  • 15
0

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>',
                ),
            )
intexbenq
  • 11
  • 1