【RESTful】Yii2实现RESTful架构配置最佳实践

标签: yiiapirestrestfulyii2
6125人阅读 评论(1) 收藏 举报
分类:

Yii2实现RESTful架构配置最佳实践

为什么要用RESTful API

在服务器端,应用程序状态和功能可以分为各种资源。资源是一个有趣的概念实体,它向客户端公开。资源的例子有:应用程序对象、数据库记录、算法等等。每个资源都使用 URI (Universal Resource Identifier) 得到一个唯一的地址。所有资源都共享统一的接口,以便在客户端和服务器之间传输状态。使用的是标准的 HTTP 方法,比如 GET、PUT、POST 和 DELETE。Hypermedia 是应用程序状态的引擎,资源表示通过超链接互联。

无状态,分层,可扩展

本文为原创博客,被收录在我自己的GitHub项目中点我查看项目文件

基于Yii2的RESTful API 的实现

不用自带的REST实现方式

首先,Yii2自带了实现RESTful api的方式,但是,官方的例子过于简单,把一个资源限定成了数据库中的一个表,这显然是和REST中定义的资源不相符的,并且实际的业务需求过于复杂,不能通过一个表进行数据的操作。

所以,我们采用了另一种方式,通过使用Yii2的不同组件,完成RESTful API的构建

路由

REST要求定义资源,采用不同HTTP方式进行访问。

这里用到了框架内部的路由

在项目的配置文件/config/web.php,中,对不同资源进行路由设置,从而达到同一个URL用不同的访问方式来处理不同业务的目的。

        //url配置对应规则
        'urlManager' => [
            'enablePrettyUrl' => true,
            'showScriptName' => false,
            'rules' => [
                //配置规则,实现RESTful的方式
                'POST accounts'=>'account/login', // 登录
                'GET accounts'=>'account/get-avatar', //获取头像
                "GET accounts/status"=>'account/status', //查询登录状态

                //获取用户组信息
                "GET groups"=>"account/profile",

                //用户申请加入用户组的接口
                "GET users/ask"=>"user/apply", //申请列表
                "PUT users/<uid:\d+>"=>"user/pass", //通过
                "PATCH users/<uid:\d+>"=>"user/nopass", //不通过
                "GET users"=>"user/list",  //通过的用户列表
                "DELETE users/<uid:\d+>"=>"user/remove", //移除现有的用户
                "GET users/<uid:\d+>"=>"user/info", //网红的具体信息
                "GET users/serach"=>"user/serach", //搜索当前用户的用户


                //消息中心相关
                "GET  notices"=>"notice/list", //消息列表
                "PUT notices/<nid:\d+>"=>"notice/mark", //消息标记为已读
                "GET notices/status"=>"notice/status", //获取消息的概要
            ],

这部分的设计,参考官方文档对于RESTful实现的部分

  • GET /users: 逐页列出所有用户
  • HEAD /users: 显示用户列表的概要信息
  • POST /users: 创建一个新用户
  • GET /users/123: 返回用户 123 的详细信息
  • HEAD /users/123: 显示用户 123 的概述信息
  • PATCH /users/123 and PUT /users/123: 更新用户123
  • DELETE /users/123: 删除用户123
  • OPTIONS /users: 显示关于末端 /users 支持的动词
  • OPTIONS /users/123: 显示有关末端 /users/123 支持的动词

接收数据

我们需要获取客户端传递过来的GET,POST,Header的数据,框架自带了Yii::$app->request,可以直接得到客户端传过来的数据。

参考\yii\web\Request|\yii\console\Request $request The request component. This property is read-only.

处理数据

这部分和一般的项目一样,都用/models中的数据表对应的Model文件,继承了\yii\db\ActiveRecord的类,实现对数据表的CURD操作。

参考URL: http://www.yiichina.com/doc/guide/2.0/db-active-record

响应数据

我们在处理数据之后,需要返回给客户端对应的数据,在REST的设计规则里是这样处理的

  • Body只返回主要的数据,比如用户列表,用户的详细数据
  • Header返回其他的信息,包括页码信息,身份校验信息
  • 完全的使用HTTP状态码作为资源被请求状态的返回,比如404,403

HTTP状态码的说明如下

Code HTTP Operation Body Contents Description
200 GET,PUT 资源 操作成功
201 POST 资源,元数据 对象创建成功
202 POST,PUT,DELETE,PATCH N/A 请求已经被接受
204 DELETE,PUT,PATCH N/A 操作已经执行成功,但是没有返回数据
301 GET link 资源已被移除
303 GET link 重定向
304 GET N/A 资源没有被修改
400 GET,PSOT,PUT,DELETE,PATCH 错误提示(消息) 参数列表错误(缺少,格式不匹配)
401 GET,PSOT,PUT,DELETE,PATCH 错误提示(消息) 未授权
403 GET,PSOT,PUT,DELETE,PATCH 错误提示(消息) 访问受限,授权过期
404 GET,PSOT,PUT,DELETE,PATCH 错误提示(消息) 资源,服务未找到
405 GET,PSOT,PUT,DELETE,PATCH 错误提示(消息) 不允许的http方法
409 GET,PSOT,PUT,DELETE,PATCH 错误提示(消息) 资源冲突,或者资源被锁定
415 GET,PSOT,PUT,DELETE,PATCH 错误提示(消息) 不支持的数据(媒体)类型
429 GET,PSOT,PUT,DELETE,PATCH 错误提示(消息) 请求过多被限制
500 GET,PSOT,PUT,DELETE,PATCH 错误提示(消息) 系统内部错误
501 GET,PSOT,PUT,DELETE,PATCH 错误提示(消息) 接口未实现

格式化数据,我们的返回数据的格式为JSON

$response= Yii::$app->response;
$response->format = \yii\web\Response::FORMAT_JSON; //返回json

错误处理

通过不同的错误码,返回不同的HTTP状态码。

由于的非常频繁的调用,所以对数据进行了封装。

错误处理类Error.php


/**
 * 错误处理类
 * 
 * ------------------------------------
 * 
 * 错误处理扩展 seaslog
 * 
 * http://www.oschina.net/news/50333/seaslog-0-21
 * 
 * http://neeke.github.io/SeasLog/
 *
 * ------------------------------------
 * 
 * @author Calvin 
 * @version 1.0
 * @copyright (c) 2016,
 */

namespace app\components\error;

use Yii;

class Error {

    /**
     * 公共的错误返回处理,通过传入参数,返回对应的错误代码,这里也定义了错误返回的格式,以及对日志的记录
     *
     * @param $error_code
     * @return array
     */
    public static function errorJson($error_code) {
        $requests = Yii::$app->request; //返回值
        $post = json_encode($requests->post());
        $get = json_encode($requests->get());
        $headers = json_encode($requests->getHeaders()->toArray());

        //带入记录错误代码的文件
        $error_file = require_once \Yii::$app->basePath . "/components/error/ErrorCode.php";
        //获取http状态码,以及文字说明
        $error_info = $error_file["$error_code"];


        $http_code = $error_info['http_code'];
        $error_text = $error_info['remark'];

        $error_body = [ //设置返回的格式
            'request' => $requests->getUrl(),
            'method'=>$requests->getMethod(),
            'error_code' => $error_code,
            'error' =>$error_text,
        ];

        $response = Yii::$app->response;
        $response->statusCode=$http_code;
        $response->format = \yii\web\Response::FORMAT_JSON;
        $headers = Yii::$app->response->headers;
        $headers->add('X-Halo-Result', 0);
//        $response->data = $error_body;


//        $userIP = $requests->userIP;
        //写入日志
//        \SeasLog::error('error === {error} && error_text === {error_text}  && userIP === {userIP} && post === {post}  && get === {get} && header === {header} ', [
//            '{error}' => $error,
//            '{error_text}' => $error_file["$error"],
//            '{post}' => $post,
//            '{get}' => $get,
//            '{userIP}' => $userIP,
//            '{header}' => $headers,
//                ], $request);
//        $appLog = \Alibaba::AppLog();
//        $appLog->debug("debug-log-emssage");
//        $appLog->info("info-log-emssage");
//        $appLog->warn("warn-log-emssage");
//        $appLog->error("error-log-emssage");

        return $error_body;
    }

}

错误代码文件ErrorCode.php

/**
 * 增加对不同类型的HTTP状态码的返回
 *
 * 错误码,HTTP状态码,返回值
 */
return [
    '1001'=>[
        'http_code'=>403,
        'remark'=>"Token验证失败",
    ],
    '1002'=>[
        'http_code'=>400,
        'remark'=>"参数错误",
    ],
    '1003'=>[
        'http_code'=>400,
        'remark'=>"参数不全",
    ],
    '2001'=>[
        'http_code'=>404,
        'remark'=>"用户不存在",
    ],

];

调用错误数据返回

return Error::errorJson(1002);

文档

有句话说得好,程序员不愿意写文档,但是看到没有文档的项目又会抓狂。。。。

概括结构

一个合格的API文档应该包含下面几项

  • 概括说明
  • 加密协议
  • 数据类型
  • 错误处理
  • 接口文档
  • 参考资料

接口文档

接口文档告诉客户端,调用什么数据,怎么掉,异常了咋办。。。

  • 简单说明
  • 访问地址
  • 请求方式
  • 返回结果
  • 返回结果字段说明
  • 错误代码
  • 更新记录

总结

RESTful API的好处在于更简洁的规范了数据请求的方式,通过资源来设计数据接口,方便客户端的调用,减少沟通成本。

不过协议毕竟只是个建议,我们可以根据自己项目的实际情况,有选择的满足协议的需求,更好的为自己的项目服务。

:)

参考资料

0
0

查看评论
* 以上用户言论只代表其个人观点,不代表CSDN网站的观点或立场
    个人资料
    • 访问:533687次
    • 积分:7980
    • 等级:
    • 排名:第2945名
    • 原创:287篇
    • 转载:13篇
    • 译文:4篇
    • 评论:69条
    博客专栏
    微信订阅号
    欢迎加入QQ群
    玩家老黄历(微信小程序)
    谢谢支持~
    最新评论