介绍(Introduction) 入门(Getting Started) 应用结构(Application Structure) 请求处理(Handling Requests) 关键概念(Key Concepts) 配合数据库工作(Working with Databases) 接收用户数据(Getting Data from Users) 显示数据(Displaying Data) 安全(Security) 缓存(Caching) RESTful Web 服务(RESTful Web Services) 开发工具(Development Tools) 测试(Testing) 高级专题(Special Topics) 小部件(Widgets) 助手类(Helpers)

控制器

在创建资源类和指定资源格输出式化后, 下一步就是创建控制器操作将资源通过 RESTful APIs 展现给终端用户。

Yii 提供两个控制器基类来简化创建 RESTful 操作的工作:yii\rest\Controlleryii\rest\ActiveController, 两个类的差别是后者提供一系列将资源处理成 Active Record 的操作。 因此如果使用 Active Record 内置的操作会比较方便,可考虑将控制器类 继承 yii\rest\ActiveController, 它会让你用最少的代码完成强大的 RESTful APIs。

yii\rest\Controlleryii\rest\ActiveController 提供以下功能, 一些功能在后续章节详细描述:

yii\rest\ActiveController 额外提供以下功能:

  • 一系列常用动作:indexviewcreateupdatedeleteoptions
  • 对动作和资源进行用户认证。

创建控制器类

当创建一个新的控制器类,控制器类的命名最好使用资源名称的单数格式, 例如,提供用户信息的控制器 可命名为 UserController

创建新的操作和 Web 应用中创建操作类似, 唯一的差别是 Web 应用中调用 render() 方法渲染一个视图作为返回值, 对于 RESTful 操作直接返回数据, serializerresponse object 会处理原始数据到请求格式的转换,例如

public function actionView($id)
{
    return User::findOne($id);
}

过滤器

yii\rest\Controller 提供的大多数 RESTful API 功能通过过滤器实现。 特别是以下过滤器会按顺序执行:

这些过滤器都在 behaviors() 方法中声明, 可覆盖该方法来配置单独的过滤器,禁用某个或增加你自定义的过滤器。 例如,如果你只想用 HTTP 基础认证,可编写如下代码:

use yii\filters\auth\HttpBasicAuth;

public function behaviors()
{
    $behaviors = parent::behaviors();
    $behaviors['authenticator'] = [
        'class' => HttpBasicAuth::className(),
    ];
    return $behaviors;
}

CORS

Cross-Origin Resource Sharing 过滤器添加到控制器比添加到上述其他过滤器中要复杂一些, 因为必须在认证方法之前应用 CORS 过滤器, 因此与其他过滤器相比,需要一些稍微不同的方式来实现。 并且还要为 CORS Preflight requests 禁用身份验证, 这样浏览器就可以安全地确定是否可以事先做出请求, 而无需发送身份验证凭据。 下面显示了将 yii\filters\Cors 过滤器添加到从 yii\rest\ActiveController 扩展的控制器所需的代码:

use yii\filters\auth\HttpBasicAuth;

public function behaviors()
{
    $behaviors = parent::behaviors();

    // remove authentication filter
    $auth = $behaviors['authenticator'];
    unset($behaviors['authenticator']);
    
    // add CORS filter
    $behaviors['corsFilter'] = [
        'class' => \yii\filters\Cors::className(),
    ];
    
    // re-add authentication filter
    $behaviors['authenticator'] = $auth;
    // avoid authentication on CORS-pre-flight requests (HTTP OPTIONS method)
    $behaviors['authenticator']['except'] = ['options'];

    return $behaviors;
}

继承 ActiveController

如果你的控制器继承 yii\rest\ActiveController, 应设置 modelClass 属性 为通过该控制器返回给用户的资源类名,该类必须继承 yii\db\ActiveRecord

自定义动作

yii\rest\ActiveController 默认提供一下动作:

  • index:按页列出资源;
  • view:返回指定资源的详情;
  • create:创建新的资源;
  • update:更新一个存在的资源;
  • delete:删除指定的资源;
  • options:返回支持的 HTTP 方法。

所有这些动作通过 actions() 方法申明,可覆盖 actions() 方法配置或禁用这些动作, 如下所示:

public function actions()
{
    $actions = parent::actions();

    // 禁用 "delete" 和 "create" 动作
    unset($actions['delete'], $actions['create']);

    // 使用 "prepareDataProvider()" 方法自定义数据 provider 
    $actions['index']['prepareDataProvider'] = [$this, 'prepareDataProvider'];

    return $actions;
}

public function prepareDataProvider()
{
    // 为 "index" 动作准备和返回数据 provider
}

请参考独立动作类的参考文档学习哪些配置项有用。

执行访问检查

通过 RESTful APIs 显示数据时,经常需要检查当前用户是否有权限访问和操作所请求的资源, 在 yii\rest\ActiveController 中, 可覆盖 checkAccess() 方法来完成权限检查。

/**
 * Checks the privilege of the current user.
 *
 * This method should be overridden to check whether the current user has the privilege
 * to run the specified action against the specified data model.
 * If the user does not have access, a [[ForbiddenHttpException]] should be thrown.
 *
 * @param string $action the ID of the action to be executed
 * @param \yii\base\Model $model the model to be accessed. If `null`, it means no specific model is being accessed.
 * @param array $params additional parameters
 * @throws ForbiddenHttpException if the user does not have access
 */
public function checkAccess($action, $model = null, $params = [])
{
    // check if the user can access $action and $model
    // throw ForbiddenHttpException if access should be denied
    if ($action === 'update' || $action === 'delete') {
        if ($model->author_id !== \Yii::$app->user->id)
            throw new \yii\web\ForbiddenHttpException(sprintf('You can only %s articles that you\'ve created.', $action));
    }
}

checkAccess() 方法默认会被 yii\rest\ActiveController 默认动作所调用,如果创建新的操作并想执行权限检查, 应在新的动作中明确调用该方法。

提示: 可使用 Role-Based Access Control (RBAC) 基于角色权限控制组件 实现 checkAccess()

发现错别字或您认为此页面需要改进?
点此进入 Github 编辑!