Yii2 REST API find by field

1.7k Views Asked by At

This is api url.

/api/web/v1/users/123

Find user by id. How to change rule to find by token, not by id?

Here is a rule:

            [
                'class' => 'yii\rest\UrlRule',
                'controller' => ['v1/users'],
                'tokens' => [
                    '{id}' => '<id:\\w+>'

                   // this does not work  
                   // '{token}' => '<token:\\w+>'
                ],
            ],
1

There are 1 best solutions below

3
On BEST ANSWER

That {id} defined as a token is the one used by the built in yii\rest\ViewAction which code is this:

class ViewAction extends Action
{
    /**
     * Displays a model.
     * @param string $id the primary key of the model.
     * @return \yii\db\ActiveRecordInterface the model being displayed
     */
    public function run($id)
    {
        $model = $this->findModel($id);
        if ($this->checkAccess) {
            call_user_func($this->checkAccess, $this->id, $model);
        }

        return $model;
    }
}

$this->findModel($id) is defined under yii\rest\Action and it find models using their primary key(s). If you need to use a different token like {token} and find your model within a different attribute than its primary key then you'll need to override the view action inside your controller.

Here is an example that should work when adding '{token}' => '<token:\\w+>' to your rules:

class UserController extends ActiveController
{
    ...
    public function actions()
    {
        $actions = parent::actions();
        unset($actions['view']);
        return $actions;
    }

    public function actionView($token){
        $modelClass = $this->modelClass;
        $model = $modelClass::find()->where(['token' => $token])->one();

        if ($model === null)
            throw new \yii\web\NotFoundHttpException("Uknown user having $token as token");

        return $model;
    }

}

Also note that you will need to change your $patterns to support the new inroduced one. Your final rules may look like this:

'rules' => [
    [
        'class' => 'yii\rest\UrlRule', 
        'controller' => ['v1/users'],  
        'tokens' => [
            '{id}' => '<id:\\w+>',
            '{token}' => '<token:\\w+>'
        ]
        'patterns' => [
            'PUT,PATCH {id}' => 'update',
            'DELETE {id}' => 'delete',
            // {token} is assigned to $token when redirecting to view
            'GET,HEAD {token}' => 'view',
            'POST' => 'create',
            'GET,HEAD' => 'index',
            '{id}' => 'options',
            '' => 'options',
        ],
    ],
]