码迷,mamicode.com
首页 > Windows程序 > 详细

[CI] 使用CodeIgniter框架搭建RESTful API服务

时间:2017-06-19 23:23:08      阅读:459      评论:0      收藏:0      [点我收藏+]

标签:error   一个   sources   curl   php   json格式   accept   cte   条件   

  在2011年8月的时候,我写了一篇博客《使用CodeIgniter框架搭建RESTful API服务》,介绍了RESTful的设计概念,以及使用CodeIgniter框架实现RESTful API的方法。转眼两年过去了,REST在这两年里有了很大的改进。我对于前一篇博客中的某些方面不是很满意,所以希望能利用这次机会写一个更加完善的版本。
我的项目基于Phil Sturgeon的CodeIgniter REST Server,遵循他自己的DBAD协议。Phil的这个项目很棒,干净利落,简单实用,并且极具特色,解决了我自己项目中两个问题:在请求中查询语句的使用,以及复杂的身份验证方法。正如我前面所说,我的项目基于Phil的项目开发,并且只有一个方面不同:我给每个资源分别分配一个控制器,而不是用一个独立庞大的控制器进行统一管理。使用多个独立控制器的好处是维护起来更加简单方便。
完整的项目源码可以在awhitney42/codeigniter-restserver-resources下载。
RESTful在深入探讨之前,我们先来回顾一下TESTful的概念。REST全名Representational State Transfer,中文可以译为:表现层状态转化,是一种网络服务的架构工具,而不仅仅是一套接口规范。
使用名词而不是动词你的RESTful接口应该提供访问而不是方法。
所以,这样是不可取的:
/createCustomer
/getCustomer?id=666
应该这样:
POST /customers
GET  /customers/666
所有东西都应该有IDREST的优点之一就是简洁,一定程度上来讲,REST只是一个URI的集合,每个资源都需要一个独一无二的ID作为一个标识。
GET /customers/666
GET /products/4234
使用动词进行操作在REST里,使用不同的HTTP动词进行增删改查的操作:
[td]
动词        操作
POST        新建一个资源
GET        读取一个资源
PUT        更新一个资源
DELETE        删除一个资源
使用这个REST服务的映射表来设计接口,在开发客户端的时候可以轻松上手,不用深入理解接口的含义。这套标准十分适用于REST,符合面向服务架构(SOA)的核心设计思想:服务抽离、松耦合、可复用、可发现、健全性。
通过这个一致的映射关系,客户端也知道哪个动词是幂等(Idempotent)的。幂等是指这个操作可以重复多次,并且每次都会得到相同的结果。参照HTTP规范,GET、PUT和DELETE操作是幂等的,POST操作不是幂等的。这也就是为什么在REST中使用POST来进行添加操作,而使用PUT来进行更新操作。
把东西链接起来REST中的一个核心概念是HATEOAS(Hypermedia As The Engine Of Application State),即“超媒体即应用状态引擎”。这意味着应该始终使用链接(超媒体)来获取资源信息,然后客户端通过这个链接就可以获取到不同的资源。
所以,相关的资源应当返回一条链接,而不是返回整个资源的内容。
也就是,该这样:

<officer id="1">
   <name>James T. Kirk</name>
   <rank>Captain</rank>
   <subordinates>
      <link ref="http://ncc1701/api/officers/2">
      <link ref="http://ncc1701/api/officers/3">
   </subordinates>
</officer>
而不该这样:
<officer id="1">
   <name>James T. Kirk</name>
   <rank>Captain</rank>
   <subordinates>
      <officer id="2">
         <name>Spock</name>
         <rank>Commander</rank>
      </officer>
      <officer id="3">
         <name>Doctor Leonard McCoy</name>
         <rank>Commander</rank>
      </officer>
   </subordinates>
</officer>

  返回资源的链接应该用完整的URI地址而不是相对路径,这要求客户端请求这些资源的当前状态,维持HATEOAS原则。使用完整的URI地址的好处是客户端不需要额外的了解API相关的内容,只需要简单的访问这些链接就可以了。
提供多种资源表现方式REST中的R代表Representational,即表现层,这意味着REST服务应该提供不同的表现方式,以全面支持不同的客户端请求。在一次HTTP请求中,服务器可以通过指定的表现方式返回资源,REST服务应该使用标准的表现方式,以便客户端之间的信息互通。
比如可以通过如下请求XML格式的数据:
GET /customers/666
Accept: application/xml
或者vcard格式:
GET /customers/666
Accept: application/vcard
或者pdf格式:
GET /customers/666
Accept: application/pdf
或者自定义格式:
GET /customers/666
Accept: application/vnd.mycompany.customer-v1+json
使用状态码作为回复HTTP的状态码提供了一套标准化方案,用来反馈请求的状态。
[td]

含义        解释
200        OK        确认GET、PUT和DELETE操作成功
201        Created        确认POST操作成功
304        Not Modified        用于条件GET访问,告诉客户端资源没有被修改
400        Bad Request        通常用于POST或者PUT请求,表明请求的内容是非法的
401        Unauthorized        需要授权
403        Forbidden        没有访问权限
404        Not Found        服务器上没有资源
405        Method Not Allowed        请求方法不能被用于请求相应的资源
409        Conflict        访问和当前状态存在冲突
CodeIgniterCodeIgniter是一个流行的MVC框架,很适合用来进行RESTful API开发。控制器(Controller)处理客户端的请求并返回内容,模型(Model)进行增删改查(CRUD)的操作,视图(View)用来处理资源的表现格式。不过在这个例子里,我们没有用模型,而是直接用控制器进行格式处理,这样整个项目更干净更简单。
代码可以直接在Github中获取:codeigniter-restserver-resources。
在接下来的例子里,我们用到了REST_Controller这个库,继承自原生的CI_Controller。它可以完成绝大部分繁杂的工作:处理请求、调用模块、格式化内容、返回数据。你的每个资源控制器都应该继承自REST_Controller这个类。
下面我们来看一个例子,我们假设要提供一个Widgets资源的RESTful接口:

class Widgets extends REST_Controller
get()Widgets类中的第一个函数是get(),用来响应HTTP的GET请求。这个函数调用了父类的protected函数_get(),用来获取请求中的参数ID。然后这个函数根据是否有参数ID使用widgets_model调用getWidgets()或者getWidget($id)方法,模型的返回值将会通过父类的response()函数返回,返回的内容包含对应的状态码和符合格式的数据。

[mw_shl_code=php,true]function get()
{    
    $id = $this->_get(‘id‘);
    if(!$id)
    {
        $widgets = $this->widgets_model->getWidgets();                        
        if($widgets)
            $this->response($widgets, 200); // 200 being the HTTP response code
        else
            $this->response(array(‘error‘ => ‘Couldn\‘t find any widgets!‘), 404);
    }
    $widget = $this->widgets_model->getWidget($id);
    if($widget)
        $this->response($widget, 200); // 200 being the HTTP response code
    else
        $this->response(array(‘error‘ => ‘Widget could not be found‘), 404);
}

  cURL是一个很好的命令行工具,我们可以用来测试REST服务,返回一个JSON格式的数据:

则会返回如下内容:
HTTP/1.1 200 OK
Status: 200
Content-Type: application/json
{"1":{"id":1,"name":"sprocket"},"2":{"id":2,"name":"gear"}}
请求特定的资源也很简单,这次我们去请求ID为2的widget并且通过XML格式返回:
$ curl -i -H "Accept: application/xml" -X GET http://foo.com/index.php/api/widgets/id/2
返回如下内容:

HTTP/1.1 200 OK
Status: 200
Content-Type: application/xml
<?xml version="1.0" encoding="utf-8"?>
<xml><id>2</id><name>gear</name></xml>
如果请求一个不存在的资源就会返回404的错误码:

HTTP/1.1 404 Not Found
Status: 404
Content-Type: application/xml
<?xml version="1.0" encoding="utf-8"?>
<xml><error>Widget could not be found</error></xml>
post()接下来的函数是post(),用来处理创建widget的POST请求。可以通过$this->_post_args获取请求的数据。父类通过Format.php对请求的数据进行处理并把它们放到了$this->_post_args里。接下来post()方法使用widgets_model模型调用createWidgets($data)函数,如果数据非法或者请求冲突,widgets_model模型会抛出异常并且返回异常的内容。如果调用成功,则会调用getWidget($id)函数获取最新的widget,在返回的时候会将返回值和201 (Created)的状态码一起返回。

function post()
{
    $data = $this->_post_args;
    try {
        $id = $this->widgets_model->createWidget($data);
    } catch (Exception $e) {
        // Here the model can throw exceptions like the following:
        // * Invalid input data:
                    //   throw new Exception(‘Invalid request data‘, 400);
        // * Conflict when attempting to create, like a resubmit:
                    //   throw new Exception(‘Widget already exists‘, 409)
        $this->response(array(‘error‘ => $e->getMessage()),
                                    $e->getCode());
    }
    if ($id) {
        $widget = $this->widgets_model->getWidget($id);
        $this->response($widget, 201); // 201 is the HTTP response code
    } else
        $this->response(array(‘error‘ => ‘Widget could not be created‘),
                                    404);
}

  

[CI] 使用CodeIgniter框架搭建RESTful API服务

标签:error   一个   sources   curl   php   json格式   accept   cte   条件   

原文地址:http://www.cnblogs.com/wangfenphph2/p/7051038.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!