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+>'
],
],
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',
],
],
]