首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
您现在的位置: 程式碼之家 >> 編程語言 >  >> 網頁程式設計 >> PHP 程式設計 >> PHP 入門

PHP RESTful API 實戰教學:從零建立符合 REST 架構的 Web 服務

     編輯:PHP 入門

PHP RESTful API 完整實作指南:原生 PHP 建立符合標準的 Web 服務

REST (Representational State Transfer) 是網路應用最主流的架構風格。本文示範使用原生 PHP (無框架) 從零建構完整的 RESTful Web Service,涵蓋 URI 設計、HTTP 方法對應、狀態碼、內容協商 (JSON/XML/HTML)、路由重寫、錯誤處理與測試驗證。

REST 核心原則

專案結構規劃

rest-example/
├── .htaccess           # Apache 路由重寫
├── RestController.php  # 請求分派器
├── SimpleRest.php      # 基礎回應處理類 (HTTP 狀態碼、內容協商)
├── SiteRestHandler.php # 業務邏輯處理類
└── Site.php            # 資料模型類

核心程式碼實作

1. 資料模型

<?php
// Site.php
class Site {
    private $sites = [
        1 => 'TaoBao', 2 => 'Google', 3 => 'Runoob',
        4 => 'Baidu', 5 => 'Weibo', 6 => 'Sina'
    ];

    public function getAllSite() { return $this->sites; }

    public function getSite($id) {
        return isset($this->sites[$id]) ? [$id => $this->sites[$id]] : [];
    }
}

2. 基礎回應類:HTTP 狀態碼與內容協商

<?php
// SimpleRest.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);
    }

    private function getHttpStatusMessage($statusCode) {
        $httpStatus = [
            200 => 'OK', 201 => 'Created', 204 => 'No Content',
            400 => 'Bad Request', 401 => 'Unauthorized', 404 => 'Not Found',
            500 => 'Internal Server Error', 503 => 'Service Unavailable',
            // ... 完整狀態碼表
        ];
        return $httpStatus[$statusCode] ?? $httpStatus[500];
    }

    protected function encodeJson($data) { return json_encode($data); }
    protected function encodeXml($data) {
        $xml = new SimpleXMLElement('<?xml version="1.0"?><site/>');
        foreach ($data as $k => $v) $xml->addChild($k, $v);
        return $xml->asXML();
    }
    protected function encodeHtml($data) {
        $html = "<table border='1'>";
        foreach ($data as $k => $v) $html .= "<tr><td>$k</td><td>$v</td></tr>";
        return $html . "</table>";
    }
}

3. 業務處理類:繼承基礎類,實作資源操作

<?php
// SiteRestHandler.php
require_once("SimpleRest.php");
require_once("Site.php");

class SiteRestHandler extends SimpleRest {
    public function getAllSites() {
        $site = new Site();
        $rawData = $site->getAllSite();
        $this->respond($rawData);
    }

    public function getSite($id) {
        $site = new Site();
        $rawData = $site->getSite($id);
        $this->respond($rawData);
    }

    private function respond($rawData) {
        $statusCode = empty($rawData) ? 404 : 200;
        if (empty($rawData)) $rawData = ['error' => 'No sites found!'];

        $contentType = $_SERVER['HTTP_ACCEPT'] ?? 'application/json';
        $this->setHttpHeaders($contentType, $statusCode);

        if (strpos($contentType, 'application/json') !== false) {
            echo $this->encodeJson($rawData);
        } elseif (strpos($contentType, 'text/html') !== false) {
            echo $this->encodeHtml($rawData);
        } elseif (strpos($contentType, 'application/xml') !== false) {
            echo $this->encodeXml($rawData);
        }
    }
}

4. 控制器:路由分派

<?php
// RestController.php
require_once("SiteRestHandler.php");

$view = $_GET['view'] ?? '';
$handler = new SiteRestHandler();

switch ($view) {
    case 'all':
        $handler->getAllSites();
        break;
    case 'single':
        $handler->getSite($_GET['id'] ?? '');
        break;
    default:
        header("HTTP/1.1 404 Not Found");
        echo json_encode(['error' => 'Not Found']);
}

5. Apache 路由重寫

# .htaccess
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]

API 端點與測試

原則說明
資源導向URI 識別資源,非動作 (如 /users/123 而非 /getUser?id=123)
統一介面HTTP 方法對應 CRUD:GET(讀)、POST(建)、PUT/PATCH(更新)、DELETE(刪)
無狀態每個請求包含完整資訊,伺服器不保存客戶端狀態
可快取回應標示可快取性 (ETag, Cache-Control)
分層系統客戶端不需知曉中間代理、負載平衡器

使用 curl 測試

# 取得所有站點 (JSON)
curl -H "Accept: application/json" https://localhost/restexample/site/list/

# 取得 ID=3 站點 (XML)
curl -H "Accept: application/xml" https://localhost/restexample/site/list/3/

# 瀏覽器直接訪問 (HTML)
# https://localhost/restexample/site/list/

進階擴充:完整 CRUD 實作

// SiteRestHandler.php 擴充
public function createSite($data) {
    // 驗證 $data
    $newId = max(array_keys($this->sites)) + 1;
    $this->sites[$newId] = $data['name'];
    $this->respond(['id' => $newId, 'name' => $data['name']], 201);
}

public function updateSite($id, $data) {
    if (!isset($this->sites[$id])) $this->respond(['error' => 'Not found'], 404);
    $this->sites[$id] = $data['name'];
    $this->respond(['id' => $id, 'name' => $data['name']]);
}

public function deleteSite($id) {
    if (!isset($this->sites[$id])) $this->respond(['error' => 'Not found'], 404);
    unset($this->sites[$id]);
    $this->respond([], 204); // No Content
}

控制器擴充

$method = $_SERVER['REQUEST_METHOD'];
$path = parse_url($_SERVER['REQUEST_URI'], PHP_URL_PATH);
$pathParts = explode('/', trim($path, '/'));

if ($pathParts[0] === 'site' && $pathParts[1] === 'list') {
    $id = $pathParts[2] ?? null;

    switch ($method) {
        case 'GET':
            $id ? $handler->getSite($id) : $handler->getAllSites();
            break;
        case 'POST':
            $input = json_decode(file_get_contents('php://input'), true);
            $handler->createSite($input);
            break;
        case 'PUT':
        case 'PATCH':
            $input = json_decode(file_get_contents('php://input'), true);
            $handler->updateSite($id, $input);
            break;
        case 'DELETE':
            $handler->deleteSite($id);
            break;
        default:
            header("HTTP/1.1 405 Method Not Allowed");
    }
}

安全性與最佳實務

  1. 輸入驗證:所有輸入嚴格驗證、清理
  2. 認證授權:JWT、API Key、OAuth2 整合
  3. 速率限制:防止濫用 (Token Bucket、Leaky Bucket)
  4. HTTPS 強制:生產環境強制 TLS
  5. 錯誤資訊最小化:生產環境隱藏堆疊追蹤
  6. 版本控制:URI 包含版本 /v1/site/list/ 或 Header 版本協商
  7. API 文件:OpenAPI/Swagger 自動生成

總結

使用原生 PHP 建構 RESTful API 能深入理解 HTTP 語意、路由分派、內容協商等核心機制。生產環境建議採用成熟框架 (Laravel, Slim, Symfony) 獲得路由、中介軟體、驗證、ORM 等開箱即用功能,但理解底層實作原理對除錯、效能調優、架構決策至關重要。

  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved
資源HTTP 方法URI說明
站點列表GET/site/list/取得所有站點
單一站點GET/site/list/{id}/取得指定 ID 站點