yiiyii-url-manageryii-routing

Yii router rule to redirect a keyword to an action's $_GET Parametric


In Yii, is it possible to use the router rule to "translate" a keyword in a URL to a certain action's $_GET Parametric?

What I want, is to let this URL:

http://example.com/MyModule/MyController/index/foo

to point to:

http://example.com?r=MyModule/MyController/index&id=12

where foo points to 12.

And, since I am using "path" urlFormat, and are using other url rules to hide index and id=, the URL above should eventually point to:

http://example.com/MyModule/MyController/12

Is this possibe by setting rules in the config file for urlManager component?


Solution

  • Your action should accept a parameter $id:

    public function actionView($id) {
        $model = $this->loadModel($id);
    

    What you need to do, is to modify the loadModel function in the same controller:

    /**
     * @param integer or string the ID or slug of the model to be loaded
     */
    public function loadModel($id) {
    
        if(is_numeric($id)) {
            $model = Page::model()->findByPk($id);
        } else {
            $model = Page::model()->find('slug=:slug', array(':slug' => $id));
        }
    
        if($model === null)
            throw new CHttpException(404, 'The requested page does not exist.');
    
        if($model->hasAttribute('isDeleted') && $model->isDeleted)
            throw new CHttpException(404, 'The requested page has been deleted for reasons of moderation.');
    
        // Not published, do not display
        if($model->hasAttribute('isPublished') && !$model->isPublished)
            throw new CHttpException(404, 'The requested page is not published.');
    
        return $model;
    }
    

    Then, you will need to modify the urlManager rules to accept a string, instead of just an ID:

    Remove :\d+ in the default rule below:

    '<controller:\w+>/<id:\d+>' => '<controller>/view',
    

    It should be like this:

    '<controller:\w+>/<id>' => '<controller>/view',
    

    One more thing to note, if you are going this path, make sure slug is unique in your database, and you should also enforce the validation rule in the model:

        array('slug', 'unique'),