使用 yii 实现 REST 风格接口

来源:互联网 发布:网络清洁器 编辑:程序博客网 时间:2024/05/22 04:47

在 PHP 界有很多开发框架, yii 是其中一个比较优秀的框架。很多人都说 yii 比较复杂,先上手可以学习 ci 、 cakephp 什么的,其实我倒不这么认为, PHP 现在的框架一般整体的思路都差不多,都号称 MVC 那一套,其实关于是不是 MVC ,怎么个 MVC 法,这个话题太大,坑太深,不谈。其实,也就是说大家抽象的方式都类似,所以如果是要将 PHP 作为工具实用,而非研究,那就还是直接从牛人的肩膀上开始吧。当然,除了 yii 我另外还推荐 Laravel 框架。我个人感觉 php 的框架到这个地步就算是开始平稳了吧( yaf 另论)。总而言之,这些是废话,对于 PHP 这种,生而为 web ,死而为 web 的语言,实用、简单是根本。什么 dirty 不 dirty 、优雅不优雅的,非我等鼠辈所能 hold 住。

回到正题,现在我们利用 yii 框架来实现一个 REST 风格的调用接口。说到 REST ,现在大多的所谓 REST 风格,没有达到真正 REST 定义的那样,不过面向实用我们不必拘泥这些概念上的问题,如果有看官觉得觉得实现不够 REST 敬请拍砖,具体问题我们可以具体讨论。

首先做一下接口的 URL 规划,假设我们要面对的资源是 item ,现在我们暴露5个接口供其他应用调用,分别是:

对于所有 item 列表调用: GET /rest/item
对于某个 item 信息调用: GET /rest/item/(\d+)
创建一个 item: POST /rest/item
更新一个 item: PUT /rest/item/(\d+)
删除一个 item: DELETE /rest/item/(\d+)

然后根据规划在主配置里注册路由:

?
1
2
3
4
5
6
7
8
9
10
11
'urlManager'=>array(
  'urlFormat'=>'path',
  'rules'=>array(
    // REST routers
    array('rest/list','pattern'=>'rest/item','verb'=>'GET'),
    array('rest/view','pattern'=>'rest/item/','verb'=>'GET'),
    array('rest/create','pattern'=>'rest/item','verb'=>'POST'),
    array('rest/update','pattern'=>'rest/item/','verb'=>'PUT'),
    array('rest/delete','pattern'=>'rest/item/','verb'=>'DELETE'),
  ),
),

这里需要吐槽一下官方文档,路由配置这块基本什么说明都没写,比如rules数组中的配置数组,里的各种参数含义,比如verb,利用这个参数就能好好的绑定路由,不必再到controller里进行判断了。只有api参考里有些关于属性和方法的说明,主要信息来源还得靠在 Google 中自行寻觅。

然后开始编写 REST 的 Controller,安装 yii 框架的约定,我们建立 protected/controllers/RestController.php ,文件内容结构如下:

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
class RestController extends Controller
{
  // Actions
  publicfunction actionList()
  {
  }
  publicfunction actionView()
  {
  }
  publicfunction actionCreate()
  {
  }
  publicfunction actionUpdate()
  {
  }
  publicfunction actionDelete()
  {
  }
  // Assistant Functions
  privatefunction _sendResponse()
  {
  }
  privatefunction _getStatusCodeMessage()
  {
  }
}

获取 item 列表的方法:

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
public function actionList()
{
  $items= Item::model()->findAll();
  if(empty($items))
  {
    $this->_sendResponse(200,'No items');
  }
  else
  {
    $rows= array();
    foreach($itemsas $item)
      $rows[] =$item->attributes;
    $this->_sendResponse(200, CJSON::encode($rows));
  }
}

获取某一 item 的方法:

?
1
2
3
4
5
6
7
8
9
10
public function actionView()
{
  if(!isset($_GET['id']))
    $this->_sendResponse(500,'Item ID is missing' );
  $item= Item::model()->findByPk($_GET['id']);
  if(is_null($item))
    $this->_sendResponse(404,'No Item found');
  else
    $this->_sendResponse(200, CJSON::encode($item));
}

新建一个 Item 的方法:

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
public function actionCreate()
{
  $item= new Item; 
  foreach($_POSTas $var=>$value)
  {
    if($item->hasAttribute($var))
      $item->$var= $value;
    else
      $this->_sendResponse(500,'Parameter Error');
  }
  if($item->save())
    $this->_sendResponse(200, CJSON::encode($item));
  else
    $this->_sendResponse(500,'Could not Create Item');
}

更新一个 item 的方法:

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
public function actionUpdate()
{
  //获取 put 方法所带来的 json 数据
  $json= file_get_contents('php://input');
  $put_vars= CJSON::decode($json,true);
  
  $item= Item::model()->findByPk($_GET['id']);
   
  if(is_null($item))
    $this->_sendResponse(400,'No Item found');
 
  foreach($put_varsas $var=>$value)
  {
    if($item->hasAttribute($var))
      $item->$var= $value;
    else
      $this->_sendResponse(500,'Parameter Error');
  }
 
  if($item->save())
    $this->_sendResponse(200, CJSON::encode($item));
  else
    $this->_sendResponse(500,'Could not Update Item');
}

删除某一 item 的方法:

?
1
2
3
4
5
6
7
8
9
10
public function actionDelete()
{
  $item= Item::model()->findByPk($_GET['id']);
  if(is_null)
    $this->_sendResponse(400,'No Item found');
  if($item->delete())
    $this->_sendResponse(200,'Delete Success');
  else
    $this->_sendResponse(500,'Could not Delete Item');
}

辅助方法。

返回响应的方法:

?
1
2
3
4
5
6
7
8
private function _sendResponse($status= 200, $body = '', $content_type= 'text/html')
{
  $status_header= 'HTTP/1.1 ' . $status . ' ' . $this->_getStatusCodeMessage($status);
  header($status_header);
  header('Content-type: '. $content_type);
  echo$body;
  Yii::app()->end();
}

获取 http 状态码的方法:

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
private function _getStatusCodeMessage($status)
{
  $codes= Array(
    200 =>'OK',
    400 =>'Bad Request',
    401 =>'Unauthorized',
    402 =>'Payment Required',
    403 =>'Forbidden',
    404 =>'Not Found',
    500 =>'Internal Server Error',
    501 =>'Not Implemented',
  );
  return(isset($codes[$status])) ?$codes[$status] :'';
}

这样我们就用 yii 框架实现了一个简单的对应某个 model 的 REST 风格的 json 调用接口。这里只实现了一些大框架的东西,具体到验证,数据的再组织都没有涉及。不过使用框架的好处就是程序组织都已经有人帮你考虑好了,按照框架的开发方式,再加上一些需要的功能是很方便的。

0 0
原创粉丝点击