您的位置:首页 > 编程语言 > PHP开发

Yii2的RESTful API开发

2015-06-08 08:50 691 查看
参考文档:http://www.yiiframework.com/doc-2.0/guide-rest.html

以 DB 中的 news 表为例创建该资源的 RESTful API,最终的测试通过工具 POSTMAN 测试如下图;



通过 yii2 ,非常方便的创建 RESTful API

步骤:

准备工作,配置友好的 URLManager

创建News Model (via gii)

创建News Controller

测试用 POSTMAN 工具或者 CURL

Restful Api 验证和授权

1. 配置 friendly Url

'urlManager' => [
'enablePrettyUrl' => true,
'showScriptName' => false,
'enableStrictParsing' => true,
'rules' => [
'<controller:\w+>/<id:\d+>' => '<controller>/view',
'<controller:\w+>/<action:\w+>/<id:\d+>' => '<controller>/<action>',
'<controller:\w+>/<action:\w+>' => '<controller>/<action>',
['class' => 'yii\rest\UrlRule', 'controller' => ['user', 'news']],
],
]

.htaccess 不要遗漏

更新20140731:特别说明, 上面的
rules
配置有误, 用于
yii1.x
版本中的
rules
(前三行)在这个地方时多余的,而且引起了一个很严重的 bug



测试的过程中遇到一个这样的问题, 报错 405 yii2 RESTful API 405 Method Not Allowed

比如请求 PUT 方法 的 http://192.168.4.126/news/162?access-token=100-token
{
"type": "yii\\web\\MethodNotAllowedHttpException",
"name": "Method Not Allowed",
"message": "Method Not Allowed. This url can only handle the following request methods: GET, HEAD.",
"code": 0,
"status": 405
}

这里由于不是在 yii2 的前台框架体系中,因此没有看到堆栈的调试信息,但是要调试也要找到这个报错 message 的所在:

yii2\filters\VerbFilter.php

public function beforeAction($event)
{
$action = $event->action->id;
if (isset($this->actions[$action])) {
$verbs = $this->actions[$action];
} elseif (isset($this->actions['*'])) {
$verbs = $this->actions['*'];
} else {
return $event->isValid;
}

$verb = Yii::$app->getRequest()->getMethod();
$allowed = array_map('strtoupper', $verbs);
if (!in_array($verb, $allowed)) {
$event->isValid = false;
// http://www.w3.org/Protocols/rfc2616/rfc2616-sec14.html#sec14.7 Yii::$app->getResponse()->getHeaders()->set('Allow', implode(', ', $allowed));
throw new MethodNotAllowedHttpException('Method Not Allowed. This url can only handle the following request methods: ' . implode(', ', $allowed) . '.');
}

return $event->isValid;
}

这里调试打印一下
$action
, 发现每次无论传入什么
$event
->action->id
都是
view


因此我断定问题出在 URL, yii 没有正确辨识出
http://192.168.4.126/news/163


去看看 config 中的
URLManager Rules
, 这里当时多余的把 老式的 url rules 放在这里,去掉试试

'rules' => [
#'<controller:\w+>/<id:\d+>' => '<controller>/view',
#'<controller:\w+>/<action:\w+>/<id:\d+>' => '<controller>/<action>',
#'<controller:\w+>/<action:\w+>' => '<controller>/<action>',
['class' => 'yii\rest\UrlRule', 'controller' => ['users', 'news']],
],

果然, 解决了问题





2. 创建 News Model

http://localhost/gii/model

3. 创建 News Controller

<?php

namespace app\controllers;

use yii\rest\ActiveController;

class NewsController extends ActiveController
{
public $modelClass = 'app\models\News';
}

4. 测试

用Chrome工具 POSTMAN 测试

GET /news: list all news page by page;
HEAD /news: show the overview information of new listing;
POST /news: create a new new;
GET /news/123: return the details of the new 123;
HEAD /news/123: show the overview information of new 123;
PATCH /news/123 and PUT /news/123: update the new 123;
DELETE /news/123: delete the new 123;
OPTIONS /news: show the supported verbs regarding endpoint /news;
OPTIONS /news/123: show the supported verbs regarding endpoint /news/123.




遗留问题: 如何用 POSTMAN 工具测试 PUT 方法?

用 CURL 命令行测试

GET 方法

E:\>curl http://192.168.4.126/news/126 {
"array": {
"type": "yii\\web\\UnauthorizedHttpException",
"name": "Unauthorized",
"message": "You are requesting with an invalid access token.",
"code": 0,
"status": 401
}
}

授权访问

E:\>curl http://192.168.4.126/news/126?access-token=100-token {
"array": {
"id": "126",
"image": "201_img.jpg",
"link": "http:\\/\\/www.surveymonkey.com\\/s\\/HZYZ3ZZ",
"show_date": "2012-05-15",
"state": 1,
"show_order": 18
}
}

PUT 方法

E:\>curl -X PUT -d image="test_method_put" http://192.168.4.126/news/126 {
"array": {
"type": "yii\\web\\UnauthorizedHttpException",
"name": "Unauthorized",
"message": "You are requesting with an invalid access token.",
"code": 0,
"status": 401
}
}

E:\>curl -X PUT -d image="test_method_put" http://192.168.4.126/news/126?access-token=100-token {
"array": {
"id": "126",
"image": "test_method_put",
"link": "http:\\/\\/www.surveymonkey.com\\/s\\/HZYZ3ZZ",
"show_date": "2012-05-15",
"state": 1,
"show_order": 18
}
}

E:\>curl http://192.168.4.126/news/126?access-token=100-token {
"array": {
"id": "126",
"image": "test_method_put",
"link": "http:\\/\\/www.surveymonkey.com\\/s\\/HZYZ3ZZ",
"show_date": "2012-05-15",
"state": 1,
"show_order": 18
}
}

DELETE 方法

E:\>curl -X DELETE http://192.168.4.126/news/126?access-token=100-token 
E:\>curl http://192.168.4.126/news/126?access-token=100-token {
"array": {
"type": "yii\\web\\NotFoundHttpException",
"name": "Not Found",
"message": "Object not found: 126",
"code": 0,
"status": 404
}
}

POST 方法

E:\>curl -X POST -d image="test_method_post" http://192.168.4.126/news?access-token=100-token {
"array": {
"image": "test_method_post",
"id": "165"
}
}

E:\>curl http://192.168.4.126/news/165?access-token=100-token {
"array": {
"id": "165",
"image": "test_method_post",
"link": "",
"show_date": "0000-00-00",
"state": 1,
"show_order": 0
}
}

其他方法

E:\>curl -X OPTIONS http://192.168.4.126/news/165?access-token=100-token 
E:\>curl -X OPTIONS http://192.168.4.126/news?access-token=100-token 
E:\>curl -X HEAD http://192.168.4.126/news?access-token=100-token 
E:\>curl -i http://192.168.4.126/news/165?access-token=100-token HTTP/1.1 200 OK
Date: Thu, 31 Jul 2014 06:37:40 GMT
Server: Apache/2.2.9 (Win32) PHP/5.4.30 mod_fcgid/2.3.6
X-Powered-By: PHP/5.4.30
Content-Length: 99
Content-Type: application/json; charset=UTF-8

{"id":"165","image":"test_method_post","link":"","show_date":"0000-00-00","state":1,"show_order":0}
E:\>

5. Restful Api 验证和授权

官方文档中介绍了3种发送
access-token
的方法, 方便测试的有
http basic Auth
以及
Query parameter
两种

这里简单介绍下配置的流程:

config/web.php 设置
enableSession


'user' => [
'identityClass' => 'app\models\User',
'enableAutoLogin' => true,
'enableSession' => false,
]


controllers/news.php

use yii\filters\auth\HttpBasicAuth;
use yii\helpers\ArrayHelper;
use yii\filters\auth\CompositeAuth;
use yii\filters\auth\HttpBearerAuth;
use yii\filters\auth\QueryParamAuth;
public function behaviors()
{
return ArrayHelper::merge(parent::behaviors(), [
'authenticator' => [
#这个地方使用`ComopositeAuth` 混合认证
'class' => CompositeAuth::className(),
#`authMethods` 中的每一个元素都应该是 一种 认证方式的类或者一个 配置数组
'authMethods' => [
HttpBasicAuth::className(),
HttpBearerAuth::className(),
QueryParamAuth::className(),
]
]
]);
}


models/User.php

private static $users = [
'100' => [
'id' => '100',
'username' => 'admin',
'password' => 'admin',
'authKey' => 'test100key',
'accessToken' => '100-token',
],
'101' => [
'id' => '101',
'username' => 'demo',
'password' => 'demo',
'authKey' => 'test101key',
'accessToken' => '101-token',
],
];
public static function findIdentityByAccessToken($token, $type = null)
{
foreach (self::$users as $user) {
if ($user['accessToken'] === $token) {
return new static($user);
}
}

return null;
}


两种方式测试一下:

访问 http://192.168.4.126/news/122 ,在弹出的登录对话框中输入用户名

100-token 或者 101-token, 密码任意,登录

直接访问 http://192.168.4.126/news/122?access-token=101-token
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: