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

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状态码的说明如下

CodeHTTP OperationBody ContentsDescription
200GET,PUT资源操作成功
201POST资源,元数据对象创建成功
202POST,PUT,DELETE,PATCHN/A请求已经被接受
204DELETE,PUT,PATCHN/A操作已经执行成功,但是没有返回数据
301GETlink资源已被移除
303GETlink重定向
304GETN/A资源没有被修改
400GET,PSOT,PUT,DELETE,PATCH错误提示(消息)参数列表错误(缺少,格式不匹配)
401GET,PSOT,PUT,DELETE,PATCH错误提示(消息)未授权
403GET,PSOT,PUT,DELETE,PATCH错误提示(消息)访问受限,授权过期
404GET,PSOT,PUT,DELETE,PATCH错误提示(消息)资源,服务未找到
405GET,PSOT,PUT,DELETE,PATCH错误提示(消息)不允许的http方法
409GET,PSOT,PUT,DELETE,PATCH错误提示(消息)资源冲突,或者资源被锁定
415GET,PSOT,PUT,DELETE,PATCH错误提示(消息)不支持的数据(媒体)类型
429GET,PSOT,PUT,DELETE,PATCH错误提示(消息)请求过多被限制
500GET,PSOT,PUT,DELETE,PATCH错误提示(消息)系统内部错误
501GET,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的好处在于更简洁的规范了数据请求的方式,通过资源来设计数据接口,方便客户端的调用,减少沟通成本。

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

:)

参考资料

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值