PHP RESTful

REST(英文:Representational State Transfer,简称REST) ,指的是一组架构约束条件和原则。

符合REST设计风格的Web API称为RESTful API。它从以下三个方面资源进行定义:

  • 直观简短的资源地址:URI,比如:http://example.com/resources/
  • 传输的资源:Web服务接受与返回的互联网媒体类型,比如:JSON,XML,YAM等。
  • 对资源的操作:Web服务在该资源上所支持的一系列请求方法(比如:POST,GET,PUT或DELETE)。

本教程我们将使用 PHP(不用框架) 来创建一个 RESTful web service,在文章末尾你可以下载本章节使用到的代码。

通过本教程你将学习到以下内容:

  • 创建一个 RESTful Webservice。
  • 使用原生 PHP, 不依赖任何框架。
  • URI 模式需要遵循 REST 规则。
  • RESTful service 接受与返回的格式可以是 JSON, XML等。
  • 根据不同情况响应对应的 HTTP 状态码。
  • 演示请求头的使用。
  • 使用 REST 客户端来测试 RESTful web service。

RESTful Webservice 实例

以下代码是 RESTful 服务类 Site.php

实例
<?php /* * 小白教程 RESTful 演示实例 * RESTful 服务类 */ Class Site { private $sites = array ( 1 => ' TaoBao ' , 2 => ' Google ' , 3 => ' Voidme ' , 4 => ' Baidu ' , 5 => ' Weibo ' , 6 => ' Sina ' ) ; public function getAllSite ( ) { return $this -> sites ; } public function getSite ( $id ) { $site = array ( $id => ( $this -> sites [ $id ] ) ? $this -> sites [ $id ] : $this -> sites [ 1 ] ) ; return $site ; } } ?>

RESTful Services URI 映射

RESTful Services URI 应该设置为一个直观简短的资源地址。Apache 服务器的 .htaccess 应设置好对应的 Rewrite 规则。

本实例我们将使用两个 URI 规则:

1、获取所有站点列表:

http://localhost/restexample/site/list/

2、使用 id 获取指定的站点,以下 URI 为获取 id 为 3 的站点:

http://localhost/restexample/site/list/3/

项目的 .htaccess 文件配置规则如下所示:

# 开启 rewrite 功能
Options +FollowSymlinks
RewriteEngine on

# 重写规则
RewriteRule ^site/list/$   RestController.php?view=all [nc,qsa]
RewriteRule ^site/list/([0-9]+)/$   RestController.php?view=single&id=$1 [nc,qsa]

RESTful Web Service 控制器

.htaccess 文件中,我们通过设置参数 'view' 来获取 RestController.php 文件中对应的请求,通过获取 'view' 不同的参数来分发到不同的方法上。RestController.php 文件代码如下:

实例
<?php require_once ( " SiteRestHandler.php " ) ; $view = " " ; if ( isset ( $_GET [ " view " ] ) ) $view = $_GET [ " view " ] ; /* * RESTful service 控制器 * URL 映射 */ switch ( $view ) { case " all " : // 处理 REST Url /site/list/ $siteRestHandler = new SiteRestHandler ( ) ; $siteRestHandler -> getAllSites ( ) ; break ; case " single " : // 处理 REST Url /site/show/<id>/ $siteRestHandler = new SiteRestHandler ( ) ; $siteRestHandler -> getSite ( $_GET [ " id " ] ) ; break ; case " " : // 404 - not found; break ; } ?>

简单的 RESTful 基础类

以下提供了 RESTful 的一个基类,用于处理响应请求的 HTTP 状态码,SimpleRest.php 文件代码如下:

实例
<?php /* * 一个简单的 RESTful web services 基类 * 我们可以基于这个类来扩展需求 */ class SimpleRest { private $httpVersion = " HTTP/1.1 " ; public function setHttpHeaders ( $contentType , $statusCode ) { $statusMessage = $this -> getHttpStatusMessage ( $statusCode ) ; header ( $this -> httpVersion . " " . $statusCode . " " . $statusMessage ) ; header ( " Content-Type: " . $contentType ) ; } public function getHttpStatusMessage ( $statusCode ) { $httpStatus = array ( 100 => ' Continue ' , 101 => ' Switching Protocols ' , 200 => ' OK ' , 201 => ' Created ' , 202 => ' Accepted ' , 203 => ' Non-Authoritative Information ' , 204 => ' No Content ' , 205 => ' Reset Content ' , 206 => ' Partial Content ' , 300 => ' Multiple Choices ' , 301 => ' Moved Permanently ' , 302 => ' Found ' , 303 => ' See Other ' , 304 => ' Not Modified ' , 305 => ' Use Proxy ' , 306 => ' (Unused) ' , 307 => ' Temporary Redirect ' , 400 => ' Bad Request ' , 401 => ' Unauthorized ' , 402 => ' Payment Required ' , 403 => ' Forbidden ' , 404 => ' Not Found ' , 405 => ' Method Not Allowed ' , 406 => ' Not Acceptable ' , 407 => ' Proxy Authentication Required ' , 408 => ' Request Timeout ' , 409 => ' Conflict ' , 410 => ' Gone ' , 411 => ' Length Required ' , 412 => ' Precondition Failed ' , 413 => ' Request Entity Too Large ' , 414 => ' Request-URI Too Long ' , 415 => ' Unsupported Media Type ' , 416 => ' Requested Range Not Satisfiable ' , 417 => ' Expectation Failed ' , 500 => ' Internal Server Error ' , 501 => ' Not Implemented ' , 502 => ' Bad Gateway ' , 503 => ' Service Unavailable ' , 504 => ' Gateway Timeout ' , 505 => ' HTTP Version Not Supported ' ) ; return ( $httpStatus [ $statusCode ] ) ? $httpStatus [ $statusCode ] : $status [ 500 ] ; } } ?>

RESTful Web Service 处理类

以下是一个 RESTful Web Service 处理类 SiteRestHandler.php,继承了上面我们提供的 RESTful 基类,类中通过判断请求的参数来决定返回的 HTTP 状态码及数据格式,实例中我们提供了三种数据格式: "application/json" 、 "application/xml" 或 "text/html":

SiteRestHandler.php 文件代码如下:

实例
<?php require_once ( " SimpleRest.php " ) ; require_once ( " Site.php " ) ; class SiteRestHandler extends SimpleRest { function getAllSites ( ) { $site = new Site ( ) ; $rawData = $site -> getAllSite ( ) ; if ( empty ( $rawData ) ) { $statusCode = 404 ; $rawData = array ( ' error ' => ' No sites found! ' ) ; } else { $statusCode = 200 ; } $requestContentType = $_SERVER [ ' HTTP_ACCEPT ' ] ; $this -> setHttpHeaders ( $requestContentType , $statusCode ) ; if ( strpos ( $requestContentType , ' application/json ' ) !== false ) { $response = $this -> encodeJson ( $rawData ) ; echo $response ; } else if ( strpos ( $requestContentType , ' text/html ' ) !== false ) { $response = $this -> encodeHtml ( $rawData ) ; echo $response ; } else if ( strpos ( $requestContentType , ' application/xml ' ) !== false ) { $response = $this -> encodeXml ( $rawData ) ; echo $response ; } } public function encodeHtml ( $responseData ) { $htmlResponse = " <table border='1'> " ; foreach ( $responseData as $key => $value ) { $htmlResponse .= " <tr><td> " . $key . " </td><td> " . $value . " </td></tr> " ; } $htmlResponse .= " </table> " ; return $htmlResponse ; } public function encodeJson ( $responseData ) { $jsonResponse = json_encode ( $responseData ) ; return $jsonResponse ; } public function encodeXml ( $responseData ) { // 创建 SimpleXMLElement 对象 $xml = new SimpleXMLElement ( ' <?xml version="1.0"?><site></site> ' ) ; foreach ( $responseData as $key => $value ) { $xml -> addChild ( $key , $value ) ; } return $xml -> asXML ( ) ; } public function getSite ( $id ) { $site = new Site ( ) ; $rawData = $site -> getSite ( $id ) ; if ( empty ( $rawData ) ) { $statusCode = 404 ; $rawData = array ( ' error ' => ' No sites found! ' ) ; } else { $statusCode = 200 ; } $requestContentType = $_SERVER [ ' HTTP_ACCEPT ' ] ; $this -> setHttpHeaders ( $requestContentType , $statusCode ) ; if ( strpos ( $requestContentType , ' application/json ' ) !== false ) { $response = $this -> encodeJson ( $rawData ) ; echo $response ; } else if ( strpos ( $requestContentType , ' text/html ' ) !== false ) { $response = $this -> encodeHtml ( $rawData ) ; echo $response ; } else if ( strpos ( $requestContentType , ' application/xml ' ) !== false ) { $response = $this -> encodeXml ( $rawData ) ; echo $response ; } } } ?>

接下来我们通过 http://localhost/restexample/site/list/ 访问,输出结果如下:


RESTful Web Service 客户端

接下来我们可以使用 Google Chrome 浏览器的 "Advance Rest Client" 作为 RESTful Web Service 客户端来请求我们的服务。

实例中请求 http://localhost/restexample/site/list/ 地址,接收数据类似为 Accept: application/json

请求 id 为 3 的站点 Voidme(小白教程),访问地址为 http://localhost/restexample/site/list/3/,

源码下载

实例中使用到的代码可点击以下按钮下载:

源码下载