PHP RESTful API 设计规范
基础规范
1 协议与域名
- 使用 HTTPS 协议
- API 使用专用域名:
api.example.com - 或保留在主域名下:
example.com/api
2 版本控制
// URL 路径版本控制(推荐) /API/v1/users /API/v2/users // 请求头版本控制 Accept: application/vnd.example.v1+json
路由设计
1 URL 命名规范
- 使用名词复数形式
- 不使用动词
- 使用小写字母
- 多个单词使用短横线(-)分隔
// ✅ 正确的设计 GET /api/v1/users // 用户列表 GET /api/v1/users/123 // 指定用户 POST /api/v1/users // 创建用户 PUT /api/v1/users/123 // 更新用户 DELETE /api/v1/users/123 // 删除用户 // ❌ 避免的设计 GET /api/v1/getUsers // 使用动词 GET /api/v1/UserList // 混合大小写 POST /api/v1/getUserData // 动词+连接词
2 资源嵌套
// 多级资源 GET /api/v1/users/123/orders/456 // 用户123的订单456 GET /api/v1/users/123/orders // 用户123的所有订单 // 子资源关联 GET /api/v1/users/123/profile // 用户资料 GET /api/v1/users/123/posts // 用户的文章
HTTP 方法
1 方法使用规范
// 标准操作 GET - 获取资源(幂等) POST - 创建资源(非幂等) PUT - 完整更新(幂等) PATCH - 部分更新(幂等) DELETE - 删除资源(幂等) // 实际操作示例 GET /api/v1/users // 获取用户列表 POST /api/v1/users // 创建用户 GET /api/v1/users/123 // 获取指定用户 PUT /api/v1/users/123 // 完整更新用户 PATCH /api/v1/users/123 // 部分更新用户 DELETE /api/v1/users/123 // 删除用户
请求设计
1 请求头规范
header('Content-Type: application/json; charset=utf-8');
header('Accept: application/json');
header('Authorization: Bearer {token}');
header('X-App-Version: 1.0.0'); // 客户端版本
header('X-Device-Id: unique-device-id'); // 设备标识
2 查询参数
// 筛选 GET /api/v1/users?status=active&age_group=20-30 // 排序 GET /api/v1/users?sort=-created_at // 降序 GET /api/v1/users?sort=created_at // 升序 // 分页 GET /api/v1/users?page=1&limit=20 // 字段选择 GET /api/v1/users?fields=id,name,email
响应设计
1 统一响应格式
// 成功响应
{
"code": 200,
"message": "success",
"data": {
"id": 1,
"name": "张三",
"email": "zhangsan@example.com"
},
"meta": {
"timestamp": 1634567890,
"copyright": "2024 Company"
}
}
// 列表响应
{
"code": 200,
"message": "success",
"data": [
{
"id": 1,
"name": "张三"
},
{
"id": 2,
"name": "李四"
}
],
"pagination": {
"total": 100,
"page": 1,
"limit": 20,
"pages": 5
}
}
2 错误响应
// 4xx 客户端错误
{
"code": 400,
"message": "请求参数错误",
"errors": {
"email": ["邮箱格式不正确"],
"password": ["密码长度不少于6位"]
}
}
// 5xx 服务器错误
{
"code": 500,
"message": "服务器内部错误",
"request_id": "a1b2c3d4-e5f6-g7h8"
}
PHP 实现示例
1 路由配置
// config/routes.php
<?php
use App\Controllers\UserController;
$routes = [
// 用户路由
'GET' => [
'/api/v1/users' => [UserController::class, 'index'],
'/api/v1/users/{id}' => [UserController::class, 'show'],
'/api/v1/users/{id}/orders' => [OrderController::class, 'getUserOrders'],
],
'POST' => [
'/api/v1/users' => [UserController::class, 'store'],
'/api/v1/users/login' => [AuthController::class, 'login'],
],
'PUT' => [
'/api/v1/users/{id}' => [UserController::class, 'update'],
],
'PATCH' => [
'/api/v1/users/{id}' => [UserController::class, 'partialUpdate'],
],
'DELETE' => [
'/api/v1/users/{id}' => [UserController::class, 'destroy'],
],
];
2 控制器基类
// app/Controllers/BaseController.php
<?php
class BaseController
{
protected function success($data = null, $code = 200, $message = 'success')
{
http_response_code($code);
header('Content-Type: application/json; charset=utf-8');
$response = [
'code' => $code,
'message' => $message,
'data' => $data,
'meta' => [
'timestamp' => time()
]
];
echo json_encode($response);
exit;
}
protected function error($message, $code = 400, $errors = null)
{
http_response_code($code);
header('Content-Type: application/json; charset=utf-8');
$response = [
'code' => $code,
'message' => $message,
'errors' => $errors
];
echo json_encode($response);
exit;
}
protected function paginate($data, $page, $limit, $total)
{
http_response_code(200);
header('Content-Type: application/json; charset=utf-8');
$response = [
'code' => 200,
'message' => 'success',
'data' => $data,
'pagination' => [
'total' => $total,
'page' => $page,
'limit' => $limit,
'pages' => ceil($total / $limit)
]
];
echo json_encode($response);
exit;
}
protected function validate($data, $rules)
{
// 实现验证逻辑
$errors = [];
foreach ($rules as $field => $rule) {
if (!isset($data[$field]) || !preg_match($rule, $data[$field])) {
$errors[$field] = "字段:{$field} 验证失败";
}
}
if (!empty($errors)) {
$this->error('验证失败', 422, $errors);
}
return true;
}
protected function getRequestData()
{
// 获取JSON请求体
$json = file_get_contents('php://input');
$data = json_decode($json, true);
if (json_last_error() !== JSON_ERROR_NONE) {
$this->error('无效的JSON格式', 400);
}
return $data ?: [];
}
protected function getAuthUser()
{
// 从请求头获取Authorization
$headers = getallheaders();
$auth = $headers['Authorization'] ?? '';
if (preg_match('/Bearer\s+(.*)/', $auth, $matches)) {
// 解析token并返回用户
return JWT::decode($matches[1]);
}
return null;
}
}
3 用户控制器
// app/Controllers/UserController.php
<?php
class UserController extends BaseController
{
private $userModel;
public function __construct()
{
$this->userModel = new UserModel();
}
// 获取用户列表
public function index(Request $request)
{
// 参数校验
$page = $request->query('page', 1);
$limit = $request->query('limit', 20);
$limit = min($limit, 100); // 限制最大条数
// 构建查询条件
$conditions = [];
if ($request->query('status')) {
$conditions[] = "status = '{$request->query('status')}'";
}
if ($request->query('fields')) {
$fields = explode(',', $request->query('fields'));
$select = implode(',', $fields);
} else {
$select = '*';
}
// 排序
$sort = $request->query('sort', '-created_at');
$sortDirection = str_starts_with($sort, '-') ? 'DESC' : 'ASC';
$sortField = ltrim($sort, '-');
// 查询数据
$users = $this->userModel->getUsers(
$conditions,
$sortField,
$sortDirection,
$page,
$limit,
$select
);
$total = $this->userModel->countUsers($conditions);
return $this->paginate($users, $page, $limit, $total);
}
// 获取指定用户
public function show($id)
{
// 参数验证
if (!is_numeric($id)) {
return $this->error('无效的用户ID', 400);
}
$user = $this->userModel->find($id);
if (!$user) {
return $this->error('用户不存在', 404);
}
// 去除敏感字段(如密码)
unset($user['password']);
return $this->success($user);
}
// 创建用户
public function store()
{
$data = $this->getRequestData();
// 数据验证
$rules = [
'name' => '/^[\x{4e00}-\x{9fa5}a-zA-Z0-9]{2,30}$/u',
'email' => '/^[\w\.-]+@[\w\.-]+\.\w+$/',
'password' => '/^.{6,32}$/'
];
$this->validate($data, $rules);
// 检查邮箱唯一性
if ($this->userModel->findByEmail($data['email'])) {
return $this->error('邮箱已被注册', 409);
}
// 密码加密
$data['password'] = password_hash($data['password'], PASSWORD_BCRYPT);
// 创建用户
$userId = $this->userModel->create($data);
if (!$userId) {
return $this->error('用户创建失败', 500);
}
// 返回创建成功的用户
$user = $this->userModel->find($userId);
unset($user['password']);
return $this->success($user, 201, '用户创建成功');
}
// 完整更新用户
public function update($id)
{
$user = $this->userModel->find($id);
if (!$user) {
return $this->error('用户不存在', 404);
}
$data = $this->getRequestData();
// 验证必需字段
$rules = [
'name' => '/^[\x{4e00}-\x{9fa5}a-zA-Z0-9]{2,30}$/u',
'email' => '/^[\w\.-]+@[\w\.-]+\.\w+$/'
];
$this->validate($data, $rules);
// 更新用户
$result = $this->userModel->update($id, $data);
if (!$result) {
return $this->error('用户更新失败', 500);
}
$updatedUser = $this->userModel->find($id);
unset($updatedUser['password']);
return $this->success($updatedUser);
}
// 删除用户
public function destroy($id)
{
$user = $this->userModel->find($id);
if (!$user) {
return $this->error('用户不存在', 404);
}
$result = $this->userModel->delete($id);
if (!$result) {
return $this->error('用户删除失败', 500);
}
return $this->success(null, 204, '用户已删除');
}
}
安全规范
1 认证与授权
// JWT实现基础认证
class AuthController extends BaseController
{
public function login()
{
$data = $this->getRequestData();
// 验证用户名密码
$user = $this->userModel->findByEmail($data['email']);
if (!$user || !password_verify($data['password'], $user['password'])) {
return $this->error('邮箱或密码错误', 401);
}
// 生成JWT Token
$payload = [
'user_id' => $user['id'],
'exp' => time() + 7200 // 2小时过期
];
$token = JWT::encode($payload, getenv('JWT_SECRET'), 'HS256');
return $this->success([
'token' => $token,
'token_type' => 'Bearer',
'expires_in' => 7200
]);
}
}
2 限流
class RateLimiter
{
public static function check($userId = null, $limit = 100, $window = 60)
{
$key = 'rate_limit:' . ($userId ?: getClientIp());
// 使用Redis实现
$current = Redis::get($key);
if ($current === false) {
Redis::setex($key, $window, 1);
} elseif ($current >= $limit) {
throw new ApiException('请求过于频繁', 429);
} else {
Redis::incr($key);
}
}
}
最佳实践
1 缓存策略
// HTTP缓存头
header('Cache-Control: private, max-age=300');
header('ETag: "' . md5(json_encode($data)) . '"');
// 条件请求
if (isset($_SERVER['HTTP_IF_NONE_MATCH'])) {
$etag = trim($_SERVER['HTTP_IF_NONE_MATCH'], '"');
if ($etag == md5(json_encode($data))) {
http_response_code(304);
exit;
}
}
2 日志记录
class ApiLogger
{
public static function log($request, $response, $duration)
{
$logData = [
'request_time' => date('Y-m-d H:i:s'),
'duration' => $duration,
'ip' => getClientIp(),
'method' => $request['REQUEST_METHOD'],
'uri' => $request['REQUEST_URI'],
'params' => json_encode($request['QUERY_STRING']),
'response_code' => $response['code'],
'launch_client' => $request['HTTP_USER_AGENT'] ?? ''
];
// 写入日志文件
file_put_contents(
LOG_PATH . '/api_' . date('Y-m-d') . '.log',
json_encode($logData) . PHP_EOL,
FILE_APPEND
);
}
}
3 异常处理
// 全局异常处理
class ApiException extends Exception
{
private $errors;
public function __construct($message, $code = 400, $errors = null)
{
parent::__construct($message, $code);
$this->errors = $errors;
}
public function getErrors()
{
return $this->errors;
}
}
// 自定义错误处理函数
set_exception_handler(function ($exception) {
if ($exception instanceof ApiException) {
$response = [
'code' => $exception->getCode(),
'message' => $exception->getMessage(),
'errors' => $exception->getErrors()
];
} else {
$response = [
'code' => 500,
'message' => '服务器内部错误',
'request_id' => uniqid()
];
}
http_response_code($response['code']);
header('Content-Type: application/json; charset=utf-8');
echo json_encode($response);
});
文档与测试
1 API文档规范
- 使用OpenAPI/Swagger规范
- 记录所有请求参数
- 提供完整示例
# api-docs.yaml
/users:
get:
summary: 获取用户列表
parameters:
- name: page
in: query
description: 页码
schema:
type: integer
- name: limit
in: query
description: 每页数量
schema:
type: integer
responses:
'200':
description: 成功
content:
application/json:
schema:
type: object
properties:
code:
type: integer
data:
type: array
2 测试规范
// 使用PHPUnit进行API测试
class UserApiTest extends PHPUnit\Framework\TestCase
{
protected $client;
protected function setUp(): void
{
$this->client = new GuzzleHttp\Client([
'base_uri' => 'https://api.example.com/v1/',
'headers' => [
'Authorization' => 'Bearer ' . $this->getToken()
]
]);
}
public function testCreateUser()
{
$response = $this->client->post('users', [
'json' => [
'name' => 'Test User',
'email' => 'test@gmail.com',
'password' => 'test123456'
]
]);
$this->assertEquals(200, $response->getStatusCode());
$data = json_decode($response->getBody(), true);
$this->assertEquals('success', $data['message']);
}
}
验收清单
- [ ] 使用HTTPS协议
- [ ] URL使用复数名词
- [ ] 正确使用HTTP方法
- [ ] 统一响应格式
- [ ] 包含分页元数据
- [ ] 实现请求验证
- [ ] 返回明确错误信息
- [ ] 实现JWT认证
- [ ] 配置CORS
- [ ] 实现限流机制
- [ ] 编写API文档
- [ ] 添加单元测试
通过遵循这些规范,可以构建出可维护、可扩展且安全的RESTful API,为前端和其他系统提供清晰、一致的接口服务。

版权声明:NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播