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
Class Site {
    private $sites = array(
        1 => 'TaoBao',
        2 => 'Google',
        3 => 'zaixian',
        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"];
switch($view){
    case "all":
        
        $siteRestHandler = new SiteRestHandler();
        $siteRestHandler->getAllSites();
        break;
    case "single":
        
        $siteRestHandler = new SiteRestHandler();
        $siteRestHandler->getSite($_GET["id"]);
        break;
    case "" :
        
        break;
}
?>
  
簡單的 RESTful 基礎類
以下提供了 RESTful 的一個基類,用於處理回應請求的 HTTP 狀態碼,SimpleRest.php 檔代碼如下:
實例
<?php
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) {
        
        $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 的站點 zaixian(IT研修),訪問地址為 http://localhost/restexample/site/list/3/,

源碼下載
實例中使用到的代碼可點擊以下按鈕下載:
源碼下載