首页 / PHP 入门教程 / 综合案例:RESTful API 实战

PHP 入门教程

综合案例:RESTful API 实战

本教程共 65 篇 · 第 64 篇 · 更新于 2026-07-24 · 约 12 分钟阅读

PHPPHP8RESTful APIJWT前后端分离API设计认证

64. 综合案例:RESTful API 实战

本节目标:理解 RESTful 设计原则,能够使用 PHP 构建规范的 API 接口,掌握 JWT 认证基础。

现代 Web 应用通常采用前后端分离架构,后端提供 API 接口供前端或移动端调用。本节学习如何构建规范的 RESTful API。


1. RESTful 设计原则

REST(Representational State Transfer)是一种架构风格,核心原则:

  1. 资源即 URL:每个资源有唯一的标识地址
  2. HTTP 动词表操作:GET 查、POST 增、PUT 改、DELETE 删
  3. 无状态:每次请求包含所有必要信息,服务端不保存客户端状态
  4. 统一返回格式:通常使用 JSON

用户资源 API 设计

操作方法URL说明
列表GET/api/users获取用户列表
详情GET/api/users/1获取 ID 为 1 的用户
创建POST/api/users新建用户
更新PUT/api/users/1更新用户信息
删除DELETE/api/users/1删除用户

2. 路由与入口

<?php
// public/api.php
header('Content-Type: application/json; charset=utf-8');

require_once __DIR__ . '/../config/database.php';
require_once __DIR__ . '/../src/UserApi.php';
require_once __DIR__ . '/../src/JwtAuth.php';

$method = $_SERVER['REQUEST_METHOD'];
$path   = parse_url($_SERVER['REQUEST_URI'], PHP_URL_PATH);
$path   = str_replace('/api.php', '', $path);

$api = new UserApi();

try {
    switch (true) {
        case $method === 'GET' && preg_match('#^/users$#', $path):
            echo json_encode($api->list());
            break;
        case $method === 'GET' && preg_match('#^/users/(\d+)$#', $path, $m):
            echo json_encode($api->show((int)$m[1]));
            break;
        case $method === 'POST' && preg_match('#^/users$#', $path):
            JwtAuth::verify(); // 需要登录
            $data = json_decode(file_get_contents('php://input'), true);
            http_response_code(201);
            echo json_encode($api->create($data));
            break;
        case $method === 'PUT' && preg_match('#^/users/(\d+)$#', $path, $m):
            JwtAuth::verify();
            $data = json_decode(file_get_contents('php://input'), true);
            echo json_encode($api->update((int)$m[1], $data));
            break;
        case $method === 'DELETE' && preg_match('#^/users/(\d+)$#', $path, $m):
            JwtAuth::verify();
            $api->delete((int)$m[1]);
            http_response_code(204);
            break;
        default:
            http_response_code(404);
            echo json_encode(['error' => '接口不存在']);
    }
} catch (Exception $e) {
    http_response_code(400);
    echo json_encode(['error' => $e->getMessage()]);
}
Note

生产环境建议使用 Slim、Laravel 等框架的路由系统,功能完善且经过充分测试。


3. API 响应类

<?php
// src/ApiResponse.php
class ApiResponse
{
    public static function success(mixed $data, string $message = 'ok'): array
    {
        return [
            'code'    => 200,
            'message' => $message,
            'data'    => $data,
        ];
    }

    public static function error(string $message, int $code = 400): array
    {
        return [
            'code'    => $code,
            'message' => $message,
            'data'    => null,
        ];
    }
}

4. 用户 API 实现

<?php
// src/UserApi.php
require_once __DIR__ . '/../config/database.php';

class UserApi
{
    private PDO $pdo;

    public function __construct()
    {
        $this->pdo = getPdo();
    }

    public function list(): array
    {
        $stmt = $this->pdo->query("SELECT id, username, email, created_at FROM users ORDER BY id DESC");
        return ApiResponse::success($stmt->fetchAll());
    }

    public function show(int $id): array
    {
        $stmt = $this->pdo->prepare("SELECT id, username, email, created_at FROM users WHERE id = ?");
        $stmt->execute([$id]);
        $user = $stmt->fetch();
        if (!$user) {
            throw new Exception('用户不存在');
        }
        return ApiResponse::success($user);
    }

    public function create(array $data): array
    {
        if (empty($data['username']) || empty($data['email']) || empty($data['password'])) {
            throw new Exception('参数不完整');
        }
        $hash = password_hash($data['password'], PASSWORD_DEFAULT);
        $stmt = $this->pdo->prepare("INSERT INTO users (username, email, password) VALUES (?, ?, ?)");
        $stmt->execute([$data['username'], $data['email'], $hash]);
        return ApiResponse::success(['id' => $this->pdo->lastInsertId()]);
    }

    public function update(int $id, array $data): array
    {
        $fields = [];
        $values = [];
        foreach (['username', 'email'] as $field) {
            if (!empty($data[$field])) {
                $fields[] = "{$field} = ?";
                $values[] = $data[$field];
            }
        }
        if (empty($fields)) {
            throw new Exception('没有要更新的字段');
        }
        $values[] = $id;
        $sql = "UPDATE users SET " . implode(', ', $fields) . " WHERE id = ?";
        $stmt = $this->pdo->prepare($sql);
        $stmt->execute($values);
        return ApiResponse::success(['updated' => $stmt->rowCount()]);
    }

    public function delete(int $id): void
    {
        $stmt = $this->pdo->prepare("DELETE FROM users WHERE id = ?");
        $stmt->execute([$id]);
    }
}

5. JWT 认证基础

JWT(JSON Web Token)是一种轻量级的认证机制。用户登录后服务端签发 Token,后续请求携带 Token 证明身份。

简单 JWT 实现(教学用)

<?php
// src/JwtAuth.php
class JwtAuth
{
    private static string $secret = 'your-256-bit-secret-key-here';

    public static function generate(array $payload): string
    {
        $header = json_encode(['typ' => 'JWT', 'alg' => 'HS256']);
        $payload['iat'] = time();
        $payload['exp'] = time() + 3600; // 1小时过期

        $base64Header  = str_replace(['+', '/', '='], ['-', '_', ''], base64_encode($header));
        $base64Payload = str_replace(['+', '/', '='], ['-', '_', ''], base64_encode(json_encode($payload)));

        $signature = hash_hmac('sha256', "{$base64Header}.{$base64Payload}", self::$secret, true);
        $base64Sig = str_replace(['+', '/', '='], ['-', '_', ''], base64_encode($signature));

        return "{$base64Header}.{$base64Payload}.{$base64Sig}";
    }

    public static function verify(): array
    {
        $auth = $_SERVER['HTTP_AUTHORIZATION'] ?? '';
        if (!str_starts_with($auth, 'Bearer ')) {
            throw new Exception('缺少认证信息');
        }
        $token = substr($auth, 7);
        $parts = explode('.', $token);
        if (count($parts) !== 3) {
            throw new Exception('Token 格式错误');
        }

        $signature = hash_hmac('sha256', "{$parts[0]}.{$parts[1]}", self::$secret, true);
        $base64Sig = str_replace(['+', '/', '='], ['-', '_', ''], base64_encode($signature));

        if (!hash_equals($base64Sig, $parts[2])) {
            throw new Exception('Token 签名无效');
        }

        $payload = json_decode(base64_decode(str_replace(['-', '_'], ['+', '/'], $parts[1])), true);
        if (($payload['exp'] ?? 0) < time()) {
            throw new Exception('Token 已过期');
        }

        return $payload;
    }
}
Tip

生产环境建议使用 firebase/php-jwt 等成熟库,不要自己手写 JWT 逻辑。


6. API 版本控制

RESTful API 应支持版本管理,常见方式:

  1. URL 路径/api/v1/users
  2. 请求头Accept: application/vnd.myapp.v1+json

推荐 URL 路径方式,简单直观:

<?php
$version = $_GET['version'] ?? 'v1';
$controller = "UserController{$version}";

7. API 文档

使用 Swagger/OpenAPI 描述接口,可自动生成文档和测试页面。

openapi: 3.0.0
info:
  title: 用户管理 API
  version: 1.0.0
paths:
  /api/users:
    get:
      summary: 获取用户列表
      responses:
        200:
          description: 成功
Note

zircote/swagger-php 是 PHP 社区常用的 OpenAPI 注解库,可以从代码注释生成文档。


小结

RESTful API 是现代后端开发的标准形态。掌握资源设计、HTTP 动词、状态码规范和 JWT 认证后,你就能为前端和移动端提供稳定的数据接口。


来源:参考了 php-the-right-way、RESTful API 设计规范、实战经验,改写后所得。