Yii2 Restful api设计--App接口编程
Yii2框架写一套RESTful风格的API,对照魏曦教你学
一,入门
一、目录结构
实现一个简单地RESTful API只需用到三个文件。目录如下:

- frontend
- ├─ config
- │ └ main.php
- ├─ controllers
- │ └ BookController.php
- └─ models
- └ Book.php

二、配置URL规则
1.修改服务器的rewrite规则,将所有URL全部指向index.php上,使其支持 /books/1 格式。
如果是Apache服务器,在frontend/web/ 目录中新建.htaccess文件。文件内容如下:
- RewriteEngine on
- # If a directory or a file exists, use the request directly
- RewriteCond %{REQUEST_FILENAME} !-f
- RewriteCond %{REQUEST_FILENAME} !-d
- # Otherwise forward the request to index.php
- RewriteRule . index.php
如果是Nginx服务器,修改nginx/conf/nginx.conf,在当前"server{}"的"location / {}"中添加下面红色标记内容:
- location / {
- try_files $uri $uri/ /index.php$is_args$args;
- }
2.修改frontend/config/main.php文件,为book控制器增加一个 URL 规则。这样,就能通过美化的 URL 和有意义的 http 动词进行访问和操作数据。配置如下:

- 'components' => [
- 'urlManager' => [
- 'enablePrettyUrl' => true,
- 'enableStrictParsing' => true,
- 'showScriptName' => false,
- 'rules' => [
- ['class' => 'yii\rest\UrlRule', 'controller' => 'book'],
- ],
- ],
- ],

三、创建一个model
1.在数据库中创建一张book表。book表的内容如下:

- -- ----------------------------
- -- Table structure for book
- -- ----------------------------
- DROP TABLE IF EXISTS `book`;
- CREATE TABLE `book` (
- `id` int(10) unsigned NOT NULL AUTO_INCREMENT,
- `name` char(50) NOT NULL DEFAULT '',
- `num` tinyint(3) unsigned NOT NULL DEFAULT '0',
- PRIMARY KEY (`id`)
- ) ENGINE=InnoDB AUTO_INCREMENT=6 DEFAULT CHARSET=utf8;
- -- ----------------------------
- -- Records of book
- -- ----------------------------
- INSERT INTO `book` VALUES ('1', 'toefl', '10');
- INSERT INTO `book` VALUES ('2', 'ielts', '20');
- INSERT INTO `book` VALUES ('3', 'sat', '30');
- INSERT INTO `book` VALUES ('4', 'gre', '40');
- INSERT INTO `book` VALUES ('5', 'gmat', '50');

2.在frontend/models/目录中新建Book.php。文件内容如下:

- namespace frontend\models;
- use yii\db\ActiveRecord;
- class Book extends ActiveRecord
- {
- public static function tableName()
- {
- return 'book';
- }
- }

四、创建一个控制器
在frontend/controllers/目录中新建BookController.php。控制器类扩展自 yii\rest\ActiveController。通过指定 yii\rest\ActiveController::modelClass 作为 frontend\models\Book, 控制器就能知道使用哪个模型去获取和处理数据。文件内容如下:

- namespace frontend\controllers;
- use yii\rest\ActiveController;
- class BookController extends ActiveController
- {
- public $modelClass = 'frontend\models\Book';
- }

五、测试
到这里,我们就已经完成了创建用于访问用户数据 的 RESTful 风格的 API。创建的 API 包括:

- GET /books: 列出所有的书
- HEAD /books: 显示书的列表的概要信息
- POST /books: 新增1本书
- GET /books/1: 返回 书ID=1的详细信息
- HEAD /books/1: 显示 书ID=1的概述信息
- PATCH /books/1 and PUT /books/1: 更新书ID=1的信息
- DELETE /books/1: 删除书ID=1的信息
- OPTIONS /books: 显示关于末端 /books 支持的动词
- OPTIONS /books/1: 显示有关末端 /books/1 支持的动词

可以通过Web浏览器中输入 URL http://{frontend的域名}/books 来访问API,或者使用一些浏览器插件来发送特定的 headers 请求,比如Firefox的RestClient、Chrome的Advanced Rest Client、postman等。
六、说明
1.Yii 将在末端使用的控制器的名称自动变为复数。这是因为 yii\rest\UrlRule 能够为他们使用的末端全自动复数化控制器。可以通过设置yii\rest\UrlRule::pluralize为false来禁用此行为:
- 'rules' => [
- ['class' => 'yii\rest\UrlRule', 'controller' => 'book', 'pluralize' => false],
- ],
2.可以使用fields和expand参数指定哪些字段应该包含在结果内。例如:URL http://{frontend的域名}/books?fields=name,num 将只返回 name 和 num 字段。
二,格式化响应,授权认证和速率限制
一、目录结构
先列出需要改动的文件。目录如下:

- web
- ├─ common
- │ └─ models
- │ └ User.php
- └─ frontend
- ├─ config
- │ └ main.php
- └─ controllers
- └ BookController.php

二、格式化响应
Yii2 RESTful支持JSON和XML格式,如果想指定返回数据的格式,需要配置yii\filters\ContentNegotiator::formats属性。例如,要返回JSON格式,修改frontend/controllers/BookController.php,加入红色标记代码:

- namespace frontend\controllers;
- use yii\rest\ActiveController;
- use yii\web\Response;
- class BookController extends ActiveController
- {
- public $modelClass = 'frontend\models\Book';
- public function behaviors() {
- $behaviors = parent::behaviors();
- $behaviors['contentNegotiator']['formats']['text/html'] = Response::FORMAT_JSON;
- return $behaviors;
- }
- }

返回XML格式:FORMAT_XML。formats属性的keys支持MIME类型,而values必须在yii\web\Response::formatters中支持被响应格式名称。
三、授权认证
RESTful APIs通常是无状态的,因此每个请求应附带某种授权凭证,即每个请求都发送一个access token来认证用户。
1.配置user应用组件(不是必要的,但是推荐配置):
设置yii\web\User::enableSession属性为false(因为RESTful APIs为无状态的,当yii\web\User::enableSession为false,请求中的用户认证状态就不能通过session来保持)
设置yii\web\User::loginUrl属性为null(显示一个HTTP 403 错误而不是跳转到登录界面)
具体方法,修改frontend/config/main.php,加入红色标记代码:

- 'components' => [
- ...
- 'user' => [
- 'identityClass' => 'common\models\User',
- 'enableAutoLogin' => true,
- 'enableSession' => false,
- 'loginUrl' => null,
- ],
- ...
- ]

2.在控制器类中配置authenticator行为来指定使用哪种认证方式,修改frontend/controllers/BookController.php,加入红色标记代码:

- namespace frontend\controllers;
- use yii\rest\ActiveController;
- use yii\web\Response;
- use yii\filters\auth\CompositeAuth;
- use yii\filters\auth\QueryParamAuth;
- class BookController extends ActiveController
- {
- public $modelClass = 'frontend\models\Book';
- public function behaviors() {
- $behaviors = parent::behaviors();
- $behaviors['authenticator'] = [
- 'class' => CompositeAuth::className(),
- 'authMethods' => [
- /*下面是三种验证access_token方式*/
- //1.HTTP 基本认证: access token 当作用户名发送,应用在access token可安全存在API使用端的场景,例如,API使用端是运行在一台服务器上的程序。
- //HttpBasicAuth::className(),
- //2.OAuth 2: 使用者从认证服务器上获取基于OAuth2协议的access token,然后通过 HTTP Bearer Tokens 发送到API 服务器。
- //HttpBearerAuth::className(),
- //3.请求参数: access token 当作API URL请求参数发送,这种方式应主要用于JSONP请求,因为它不能使用HTTP头来发送access token
- //http://localhost/user/index/index?access-token=123
- QueryParamAuth::className(),
- ],
- ];
- $behaviors['contentNegotiator']['formats']['text/html'] = Response::FORMAT_JSON;
- return $behaviors;
- }
- }

3.创建一张user表

- -- ----------------------------
- -- Table structure for user
- -- ----------------------------
- DROP TABLE IF EXISTS `user`;
- CREATE TABLE `user` (
- `id` int(10) unsigned NOT NULL AUTO_INCREMENT,
- `username` varchar(20) NOT NULL DEFAULT '' COMMENT '用户名',
- `password_hash` varchar(100) NOT NULL DEFAULT '' COMMENT '密码',
- `password_reset_token` varchar(50) NOT NULL DEFAULT '' COMMENT '密码token',
- `email` varchar(20) NOT NULL DEFAULT '' COMMENT '邮箱',
- `auth_key` varchar(50) NOT NULL DEFAULT '',
- `status` tinyint(3) unsigned NOT NULL DEFAULT '0' COMMENT '状态',
- `created_at` int(10) unsigned NOT NULL DEFAULT '0' COMMENT '创建时间',
- `updated_at` int(10) unsigned NOT NULL DEFAULT '0' COMMENT '更新时间',
- `access_token` varchar(50) NOT NULL DEFAULT '' COMMENT 'restful请求token',
- `allowance` int(10) unsigned NOT NULL DEFAULT '0' COMMENT 'restful剩余的允许的请求数',
- `allowance_updated_at` int(10) unsigned NOT NULL DEFAULT '0' COMMENT 'restful请求的UNIX时间戳数',
- PRIMARY KEY (`id`),
- UNIQUE KEY `username` (`username`),
- UNIQUE KEY `access_token` (`access_token`)
- ) ENGINE=InnoDB DEFAULT CHARSET=utf8;
- -- ----------------------------
- -- Records of user
- -- ----------------------------
- INSERT INTO `user` VALUES ('1', 'admin', '$2y$13$1KWwchqGvxDeORDt5pRW.OJarf06PjNYxe2vEGVs7e5amD3wnEX.i', '', '', 'z3sM2KZvXdk6mNXXrz25D3JoZlGXoJMC', '10', '1478686493', '1478686493', '123', '4', '1478686493');

在common/models/User.php类中实现 yii\web\IdentityInterface::findIdentityByAccessToken()方法。修改common/models/User.php,加入红色标记代码::

- public static function findIdentityByAccessToken($token, $type = null)
- {
- //findIdentityByAccessToken()方法的实现是系统定义的
- //例如,一个简单的场景,当每个用户只有一个access token, 可存储access token 到user表的access_token列中, 方法可在User类中简单实现,如下所示:
- return static::findOne(['access_token' => $token]);
- //throw new NotSupportedException('"findIdentityByAccessToken" is not implemented.');
- }

四、速率限制
为防止滥用,可以增加速率限制。例如,限制每个用户的API的使用是在60秒内最多10次的API调用,如果一个用户同一个时间段内太多的请求被接收,将返回响应状态代码 429 (这意味着过多的请求)。
1.Yii会自动使用yii\filters\RateLimiter为yii\rest\Controller配置一个行为过滤器来执行速率限制检查。如果速度超出限制,该速率限制器将抛出一个yii\web\TooManyRequestsHttpException。
修改frontend/controllers/BookController.php,加入红色标记代码:

- namespace frontend\controllers;
- use yii\rest\ActiveController;
- use yii\web\Response;
- use yii\filters\auth\CompositeAuth;
- use yii\filters\auth\QueryParamAuth;
- use yii\filters\RateLimiter;
- class BookController extends ActiveController
- {
- public $modelClass = 'frontend\models\Book';
- public function behaviors() {
- $behaviors = parent::behaviors();
- $behaviors['rateLimiter'] = [
- 'class' => RateLimiter::className(),
- 'enableRateLimitHeaders' => true,
- ];
- $behaviors['authenticator'] = [
- 'class' => CompositeAuth::className(),
- 'authMethods' => [
- /*下面是三种验证access_token方式*/
- //1.HTTP 基本认证: access token 当作用户名发送,应用在access token可安全存在API使用端的场景,例如,API使用端是运行在一台服务器上的程序。
- //HttpBasicAuth::className(),
- //2.OAuth 2: 使用者从认证服务器上获取基于OAuth2协议的access token,然后通过 HTTP Bearer Tokens 发送到API 服务器。
- //HttpBearerAuth::className(),
- //3.请求参数: access token 当作API URL请求参数发送,这种方式应主要用于JSONP请求,因为它不能使用HTTP头来发送access token
- //http://localhost/user/index/index?access-token=123
- QueryParamAuth::className(),
- ],
- ];
- $behaviors['contentNegotiator']['formats']['text/html'] = Response::FORMAT_JSON;
- return $behaviors;
- }
- }

2.在user表中使用两列来记录容差和时间戳信息。为了提高性能,可以考虑使用缓存或NoSQL存储这些信息。
修改common/models/User.php,加入红色标记代码:

- namespace common\models;
- use Yii;
- use yii\base\NotSupportedException;
- use yii\behaviors\TimestampBehavior;
- use yii\db\ActiveRecord;
- use yii\web\IdentityInterface;
- use yii\filters\RateLimitInterface;
- class User extends ActiveRecord implements IdentityInterface, RateLimitInterface
- {
- ....
- // 返回在单位时间内允许的请求的最大数目,例如,[10, 60] 表示在60秒内最多请求10次。
- public function getRateLimit($request, $action)
- {
- return [5, 10];
- }
- // 返回剩余的允许的请求数。
- public function loadAllowance($request, $action)
- {
- return [$this->allowance, $this->allowance_updated_at];
- }
- // 保存请求时的UNIX时间戳。
- public function saveAllowance($request, $action, $allowance, $timestamp)
- {
- $this->allowance = $allowance;
- $this->allowance_updated_at = $timestamp;
- $this->save();
- }
- ....
- public static function findIdentityByAccessToken($token, $type = null)
- {
- //throw new NotSupportedException('"findIdentityByAccessToken" is not implemented.');
- //findIdentityByAccessToken()方法的实现是系统定义的
- //例如,一个简单的场景,当每个用户只有一个access token, 可存储access token 到user表的access_token列中, 方法可在User类中简单实现,如下所示:
- return static::findOne(['access_token' => $token]);
- }
- ....
- }
Yii2 Restful api设计--App接口编程的更多相关文章
- 我是如何根据豆瓣api来理解Restful API设计的
1.什么是REST REST全称是Representational State Transfer,表述状态转移的意思.它是在Roy Fielding博士论文首次提出.REST本身没有创造新的技术.组件 ...
- Spring+SpringMVC+MyBatis+easyUI整合进阶篇(二)RESTful API实战笔记(接口设计及Java后端实现)
写在前面的话 原计划这部分代码的更新也是上传到ssm-demo仓库中,因为如下原因并没有这么做: 有些使用了该项目的朋友建议重新创建一个仓库,因为原来仓库中的项目太多,结构多少有些乱糟糟的. 而且这次 ...
- RESTful API实战笔记(接口设计及Java后端实现)
写在前面的话 原计划这部分代码的更新也是上传到ssm-demo仓库中,因为如下原因并没有这么做: 有些使用了该项目的朋友建议重新创建一个仓库,因为原来仓库中的项目太多,结构多少有些乱糟糟的. 而且这次 ...
- Yii2 Restful Api 401
采用Yii2 Restful Api方式为APP提供数据,默认你已经做好了所有的编码和配置工作.采用Postman测试接口: 出现这个画面的一个可能原因是:access_token的写法有误,如果你使 ...
- Rest Framework简介 和 RESTful API 设计指南
使用Django Rest Framework之前我们要先知道,它是什么,能干什么用? Django Rest Framework 是一个强大且灵活的工具包,用以构建Web API 为什么要使用Res ...
- 微服务指南走北(三):Restful API 设计简述
API的定义取决于选择的IPC通信方式,假设是消息机制(如 AMQP 或者 STOMP).API则由消息频道(channel)和消息类型.假设是使用HTTP机制,则是基于请求/响应(调用http的ur ...
- RESTful API设计原则与规范
RESTful API设计原则与规范 一.背景与基础概念 2 二.RESTful API应遵循的原则 3 1.协议(Protocol) 3 2.域名(ROOT URL) 3 3.版本(Versioni ...
- 从英文变形规则计算到Restful Api设计
➠更多技术干货请戳:听云博客 一天在研究Restful API设计,命名的时候我总是很纠结,我相信大多数人也有这种感觉,不是说想不出来某个单词怎么写的问题,像我这种没事背单词背到13000词量的人也要 ...
- Yii2 restful api创建,认证授权以及速率控制
Yii2 restful api创建,认证授权以及速率控制 下面是对restful从创建到速率控制的一个详细流程介绍,里面的步骤以及截图尽可能详细,熟悉restful的盆友可能觉得过于繁琐,新手不妨耐 ...
随机推荐
- 添加图片后xcode报错:resource fork, Finder information, or similar detritus not allowed
/Users/songximing/Library/Developer/Xcode/DerivedData/Children-cvqgzlzddltkfndhdmzedxbnoxwx/Build/Pr ...
- 嵌套表用法详解(PLSQL)
嵌套表 嵌套表是一种类似于索引表的结构,也可以用于保存多个数据,而且也可以保存复合类型的数据 嵌套表指的是一个数据表定义事同时加入了其他内部表的定义,这一概念是在oracle 8中引入的,它们可以使用 ...
- Python内置模块:random,os,sys,和加密模块hashlib
random import random # 导入模块 随机数 import random # 内置的 print(random.random()) #0-1 之间随机小数(18位有效数字) p ...
- 洛谷P3311 [SDOI2014]数数 AC自动机+dp
正解:AC自动机+dp 解题报告: 传送门! 首先看到多串匹配balabala显然想到建个AC自动机? 然后可以用一点儿数位dp的思想地想下(,,,其实并不算QAQ 幸运数可以分为两类:位数<n ...
- vue监听路由的变化,跳转到同一个页面时,Url改变但视图未重新加载问题
引入:https://q.cnblogs.com/q/88214/ 解决方法: 添加路由监听,路由改变时执行监听方法 methods:{ fetchData(){ console.log('路由发送变 ...
- 链接服务器XXX的OLE DB提供程序“SQLNCLI”无法启动分布式事务“
错误消息msg 7391 16级状态1行1表示 “Msg 7391,Level 16,State 2,Line 1 无法执行该操作,因为链接服务器XXX的OLE DB提供程序“SQLNCLI”无法启动 ...
- zabbix基础知识
zabbix监控 初级 1.识别监控对象(分级) 2.理解监控对象(理论知识) 3.细分监控对象的指标 4.确定报警的基准线 预中级 1.工具化和监控分离 2.监控对象的分类 2.1硬件监控(方法:机 ...
- oracle-安装-init.sh
!#/bin/bashgroupadd -g 1001 oinstallgroupadd -g 1002 dbagroupadd -g 1003 opergroupadd -g 1004 asmadm ...
- 001-dubbo基础-001-服务化最佳实践、异常处理逻辑
1.参看地址 http://dubbo.apache.org/zh-cn/ 2.服务化最佳实践 分包 建议将服务接口.服务模型.服务异常等均放在 API 包中,因为服务模型和异常也是 API 的一部分 ...
- PowerTCP FTP for .NET 在线e文文档
http://www.dart.com/help/ptftpnet/webframe.html