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

实例

  1. <?php
  2. /*
  3. * 手册网 RESTful 演示实例
  4. * RESTful 服务类
  5. */
  6. Class Site {
  7. private $sites = array(
  8. 1 => 'TaoBao',
  9. 2 => 'Google',
  10. 3 => 'Shouce',
  11. 4 => 'Baidu',
  12. 5 => 'Weibo',
  13. 6 => 'Sina'
  14. );
  15. public function getAllSite(){
  16. return $this->sites;
  17. }
  18. public function getSite($id){
  19. $site = array($id => ($this->sites[$id]) ? $this->sites[$id] : $this->sites[1]);
  20. return $site;
  21. }
  22. }
  23. ?>

RESTful Services URI 映射

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

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

1、获取所有站点列表:

  1. http://localhost/restexample/site/list/

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

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

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

  1. # 开启 rewrite 功能
  2. Options +FollowSymlinks
  3. RewriteEngine on
  4.  
  5. # 重写规则
  6. RewriteRule ^site/list/$ RestController.php?view=all [nc,qsa]
  7. RewriteRule ^site/list/([0-9]+)/$ RestController.php?view=single&id=$1 [nc,qsa]

RESTful Web Service 控制器

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

实例

  1. <?php
  2. require_once("SiteRestHandler.php");
  3. $view = "";
  4. if(isset($_GET["view"]))
  5. $view = $_GET["view"];
  6. /*
  7. * RESTful service 控制器
  8. * URL 映射
  9. */
  10. switch($view){
  11. case "all":
  12. // 处理 REST Url /site/list/
  13. $siteRestHandler = new SiteRestHandler();
  14. $siteRestHandler->getAllSites();
  15. break;
  16. case "single":
  17. // 处理 REST Url /site/show/<id>/
  18. $siteRestHandler = new SiteRestHandler();
  19. $siteRestHandler->getSite($_GET["id"]);
  20. break;
  21. case "" :
  22. //404 - not found;
  23. break;
  24. }
  25. ?>

简单的 RESTful 基础类

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

实例

  1. <?php
  2. /*
  3. * 一个简单的 RESTful web services 基类
  4. * 我们可以基于这个类来扩展需求
  5. */
  6. class SimpleRest {
  7. private $httpVersion = "HTTP/1.1";
  8. public function setHttpHeaders($contentType, $statusCode){
  9. $statusMessage = $this -> getHttpStatusMessage($statusCode);
  10. header($this->httpVersion. " ". $statusCode ." ". $statusMessage);
  11. header("Content-Type:". $contentType);
  12. }
  13. public function getHttpStatusMessage($statusCode){
  14. $httpStatus = array(
  15. 100 => 'Continue',
  16. 101 => 'Switching Protocols',
  17. 200 => 'OK',
  18. 201 => 'Created',
  19. 202 => 'Accepted',
  20. 203 => 'Non-Authoritative Information',
  21. 204 => 'No Content',
  22. 205 => 'Reset Content',
  23. 206 => 'Partial Content',
  24. 300 => 'Multiple Choices',
  25. 301 => 'Moved Permanently',
  26. 302 => 'Found',
  27. 303 => 'See Other',
  28. 304 => 'Not Modified',
  29. 305 => 'Use Proxy',
  30. 306 => '(Unused)',
  31. 307 => 'Temporary Redirect',
  32. 400 => 'Bad Request',
  33. 401 => 'Unauthorized',
  34. 402 => 'Payment Required',
  35. 403 => 'Forbidden',
  36. 404 => 'Not Found',
  37. 405 => 'Method Not Allowed',
  38. 406 => 'Not Acceptable',
  39. 407 => 'Proxy Authentication Required',
  40. 408 => 'Request Timeout',
  41. 409 => 'Conflict',
  42. 410 => 'Gone',
  43. 411 => 'Length Required',
  44. 412 => 'Precondition Failed',
  45. 413 => 'Request Entity Too Large',
  46. 414 => 'Request-URI Too Long',
  47. 415 => 'Unsupported Media Type',
  48. 416 => 'Requested Range Not Satisfiable',
  49. 417 => 'Expectation Failed',
  50. 500 => 'Internal Server Error',
  51. 501 => 'Not Implemented',
  52. 502 => 'Bad Gateway',
  53. 503 => 'Service Unavailable',
  54. 504 => 'Gateway Timeout',
  55. 505 => 'HTTP Version Not Supported');
  56. return ($httpStatus[$statusCode]) ? $httpStatus[$statusCode] : $status[500];
  57. }
  58. }
  59. ?>

RESTful Web Service 处理类

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

SiteRestHandler.php 文件代码如下:

实例

  1. <?php
  2. require_once("SimpleRest.php");
  3. require_once("Site.php");
  4. class SiteRestHandler extends SimpleRest {
  5. function getAllSites() {
  6. $site = new Site();
  7. $rawData = $site->getAllSite();
  8. if(empty($rawData)) {
  9. $statusCode = 404;
  10. $rawData = array('error' => 'No sites found!');
  11. } else {
  12. $statusCode = 200;
  13. }
  14. $requestContentType = $_SERVER['HTTP_ACCEPT'];
  15. $this ->setHttpHeaders($requestContentType, $statusCode);
  16. if(strpos($requestContentType,'application/json') !== false){
  17. $response = $this->encodeJson($rawData);
  18. echo $response;
  19. } else if(strpos($requestContentType,'text/html') !== false){
  20. $response = $this->encodeHtml($rawData);
  21. echo $response;
  22. } else if(strpos($requestContentType,'application/xml') !== false){
  23. $response = $this->encodeXml($rawData);
  24. echo $response;
  25. }
  26. }
  27. public function encodeHtml($responseData) {
  28. $htmlResponse = "<table border='1'>";
  29. foreach($responseData as $key=>$value) {
  30. $htmlResponse .= "<tr><td>". $key. "</td><td>". $value. "</td></tr>";
  31. }
  32. $htmlResponse .= "</table>";
  33. return $htmlResponse;
  34. }
  35. public function encodeJson($responseData) {
  36. $jsonResponse = json_encode($responseData);
  37. return $jsonResponse;
  38. }
  39. public function encodeXml($responseData) {
  40. // 创建 SimpleXMLElement 对象
  41. $xml = new SimpleXMLElement('<?xml version="1.0"?><site></site>');
  42. foreach($responseData as $key=>$value) {
  43. $xml->addChild($key, $value);
  44. }
  45. return $xml->asXML();
  46. }
  47. public function getSite($id) {
  48. $site = new Site();
  49. $rawData = $site->getSite($id);
  50. if(empty($rawData)) {
  51. $statusCode = 404;
  52. $rawData = array('error' => 'No sites found!');
  53. } else {
  54. $statusCode = 200;
  55. }
  56. $requestContentType = $_SERVER['HTTP_ACCEPT'];
  57. $this ->setHttpHeaders($requestContentType, $statusCode);
  58. if(strpos($requestContentType,'application/json') !== false){
  59. $response = $this->encodeJson($rawData);
  60. echo $response;
  61. } else if(strpos($requestContentType,'text/html') !== false){
  62. $response = $this->encodeHtml($rawData);
  63. echo $response;
  64. } else if(strpos($requestContentType,'application/xml') !== false){
  65. $response = $this->encodeXml($rawData);
  66. echo $response;
  67. }
  68. }
  69. }
  70. ?>

接下来我们通过 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 的站点 Shouce(手册网),访问地址为 http://localhost/restexample/site/list/3/,

源码下载

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

下载地址