PHP Yii2快速构建Web Restful API 接口服务

REST概述

REST 从资源的角度来观察整个网络,分布在各处的资源由URI确定,而客户端的应用通过URI来获取资源的表示方式。获得这些表徵致使这些应用程序转变了其状态。随着不断获取资源的表示方式,客户端应用不断地在转变着其状态,所谓表述性状态转移(Representational State Transfer)。

这一观点不是凭空臆造的,而是通过观察当前Web互联网的运作方式而抽象出来的。Roy Fielding 认为,“设计良好的网络应用表现为一系列的网页,这些网页可以看作的虚拟的状态机,用户选择这些链接导致下一网页传输到用户端展现给使用的人,而这正代表了状态的转变。”

REST是设计风格而不是标准。REST通常基于使用HTTPURI,和XML以及HTML这些现有的广泛流行的协议和标准。

REST特点

1.资源是由URI来指定。
2.对资源的操作包括获取、创建、修改和删除资源,这些操作正好对应HTTP协议提供的GETPOSTPUTDELETE方法。
3.通过操作资源的表现形式来操作资源。
4.资源的表现形式则是XML或者HTML,取决于读者是机器还是人,是消费web服务的客户软件还是web浏览器。当然也可以是任何其他的格式。

RESTful Web 服务

RESTful Web 服务(也称为 RESTful Web API)是一个使用HTTP并遵循REST原则的Web服务。
它从以下三个方面资源进行定义:URI,比如:http://example.com/resources/。
Web服务接受与返回的互联网媒体类型,比如:JSONXML YAML 等。
Web服务在该资源上所支持的一系列请求方法(比如:POSTGETPUTDELETE)。

该表列出了在实现RESTful Web 服务时HTTP请求方法的典型用途。

资源 GET PUT POST DELETE
一组资源的URI,比如http://example.com/resources/ 列出 URI,以及该资源组中每个资源的详细信息(后者可选)。 使用给定的一组资源替换当前整组资源。 在本组资源中创建/追加一个新的资源。 该操作往往返回新资源的URL。 删除 整组资源。
单个资源的URI,比如http://example.com/resources/142 获取 指定的资源的详细信息,格式可以自选一个合适的网络媒体类型(比如:XML、JSON等) 替换/创建 指定的资源。并将其追加到相应的资源组中。 把指定的资源当做一个资源组,并在其下创建/追加一个新的元素,使其隶属于当前资源。 删除 指定的元素。

PUT 和 DELETE 方法是幂等方法。GET方法是安全方法 (不会对服务器端有修改,因此也是幂等的)。不像基于SOAP的Web服务,RESTful Web服务并没有的“正式”标准。 这是因为REST是一种架构,而SOAP只是一个协议。虽然REST不是一个标准,但在实现RESTful Web服务时可以使用其他各种标准(比如HTTP,URL,XML,PNG等)。

REST优点

1.可以利用缓存Cache来提高响应速度
2.通讯本身的无状态性可以让不同的服务器的处理一系列请求中的不同请求,提高服务器的扩展性
3.浏览器即可作为客户端,简化软件需求
4.相对于其他叠加在HTTP协议之上的机制,REST的软件依赖性更小
5.不需要额外的资源发现机制
6.在软件技术演进中的长期的兼容性更好

 

Restful API服务接口开发实例

Yii 提供了一整套工具来简化RESTful服务的开发。特别是以下几个方面:
1.使用ActiveRecord的通用接口来快速构建原型;
2.应答格式协商(缺省支持 JSON 和 XML);
3.可定制的对象序列化,支持选择输出哪些列;
4.采集数据的格式化以及验证错误;
5.通过HTTP 动词检查实现高效路由;
6.支持 OPTIONS 和 HEAD 动词;
7.认证;
8.鉴权;
9.支持 HATEOAS;
10.可使用 yii\filters\HttpCache 缓存;
11.访问速度限制;
12.搜索和过滤:TBD
13.测试:TBD
14.API 文档自动生成:TBD

让我们用一个简单的例子来演示下如何构建一套 RESTful 接口。假设我们需要提供用户信息查询和更新接口,已有用户数据表为user,ActiveRecord模型类为 common\models\User

首先,创建一个控制器类,我创建在了backend项目下的api 模块里面 backend\modules\api\controllers\UserController

<?php

namespace backend\modules\api\controllers;

use yii\rest\ActiveController;

class UserController extends ActiveController
{
    public $modelClass = 'common\models\User';
}

然后,修改config中的 urlManager 配置项:

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

然后,你已经完成RESTful接口的创建任务了,就这么简单 ! 下面是默认创建的接口列表:

GET /user: 按页列举所有用户;
HEAD /user: 显示用户列表的总览信息;
POST /user: 创建一个新用户;
GET /user/123: 返回用户标识为123的用户数据;
HEAD /user/123: 显示用户123的总览信息;
PATCH /user/123 和 PUT /users/123: 更新用户123;
DELETE /user/123: 删除用户123;
OPTIONS /user: 显示终端 /users 所支持的动作(Verbs);
OPTIONS /user/123: 显示终端 /users/123 所支持的动作;

你可以使用如下 curl 命令来访问服务接口(假设localhost已经配置指向到了backend应用):

curl -i -H "Accept:application/json" "http://localhost/api/user"

执行后将返回类似如下数据:

HTTP/1.1 200 OK
Date: Sun, 02 Mar 2014 05:31:43 GMT
Server: Apache/2.2.26 (Unix) DAV/2 PHP/5.4.20 mod_ssl/2.2.26 OpenSSL/0.9.8y
X-Powered-By: PHP/5.4.20
X-Pagination-Total-Count: 1000
X-Pagination-Page-Count: 50
X-Pagination-Current-Page: 1
X-Pagination-Per-Page: 20
Link: <http://localhost/api/user?page=1>; rel=self, 
 <http://localhost/api/user?page=2>; rel=next, 
 <http://localhost/api/user?page=50>; rel=last
Transfer-Encoding: chunked
Content-Type: application/json; charset=UTF-8
[
 {
 "id": 1,
 ...
 },
 {
 "id": 2,
 ...
 },
 ...
]

修改可接受内容类型为 application/xml,可以返回XML格式的数据:

curl -i -H "Accept:application/xml" "http://localhost/api/user"

修改为xml格式后返回如下格式:

HTTP/1.1 200 OK
Date: Sun, 02 Mar 2014 05:31:43 GMT
Server: Apache/2.2.26 (Unix) DAV/2 PHP/5.4.20 mod_ssl/2.2.26 OpenSSL/0.9.8y
X-Powered-By: PHP/5.4.20
X-Pagination-Total-Count: 1000
X-Pagination-Page-Count: 50
X-Pagination-Current-Page: 1
X-Pagination-Per-Page: 20
Link: <http://localhost/api/user?page=1>; rel=self, 
 <http://localhost/api/user?page=2>; rel=next, 
 <http://localhost/api/user?page=50>; rel=last
Transfer-Encoding: chunked
Content-Type: application/xml

<?xml version="1.0" encoding="UTF-8"?>
<response>
 <item>
 <id>1</id>
 ...
 </item>
 <item>
 <id>2</id>
 ...
 </item>
 ...
</response>

提示: 你当然还可以直接通过浏览器访问这些接口,比如 http://localhost/api/user

如你所见,应答头部信息包含记录总数和页数,等等。还包括了其他页面的链接。比如,Link http://localhost/api/user?page=2 指向了下一页用户数据。

通过使用 fieldsexpand 参数,你也可以请求返回数据子集。URL http://localhost/api/users?fields=id,email 将只返回 idemail 字段数据。

 

重写字段移除敏感数据:

你可能还注意到 http://localhost/api/user 的返回数据包含了一些敏感数据如 password_hash, auth_key。你当然不想把这些信息通过公共服务接口暴露出去,你可以且应该把这些字段过滤掉。
yii\base\Model::fields() 方法声明了哪些字段 fields 要被包含进结果中。一个字段就是一个命名数据项。在结果数组中,数组的keys是字段名,而values是相应字段的值。yii\base\Model::fields() 的缺省实现返回模型所有属性;而 yii\db\ActiveRecord::fields() 缺省情况下返回那些已经被导入到该对象中的属性的名称。

你可以覆盖 fields() 方法来添加,删除,重命名或重定义字段。修改User.php model文件,加入类似下列代码来剔除掉敏感字段:

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

        // remove fields that contain sensitive information
        unset($fields['auth_key'], $fields['password_hash'], $fields['password_reset_token']);

        return $fields;
    }

也可以通过下面的方式重写,只开放出需要的字段:

public function fields()
{
    return [
        // field name is the same as the attribute name
        'id',
        // field name is "email", the corresponding attribute name is "email_address"
        'email' => 'email_address',
        // field name is "name", its value is defined by a PHP callback
        'name' => function () {
            return $this->first_name . ' ' . $this->last_name;
        },
    ];
}

 

 

参考资料

http://yii2.techbrood.com/guide-rest.html

http://www.yiiframework.com/doc-2.0/guide-rest-quick-start.html

 

 

 

 

 

 

 

共有 0 条评论

Top