c86f08c325
Co-Authored-By: Claude Code <noreply@anthropic.com>
86 lines
3.0 KiB
PHP
86 lines
3.0 KiB
PHP
<?php
|
||
/**
|
||
* 统一接口基座 v1(批次1「架构筑基」REV-ARCH-2)
|
||
*
|
||
* 所有业务接口统一走 Api::boot(),收敛「require 一串公共文件 + checkAjax +
|
||
* checkPermission + DB 连接」的重复样板,并提供统一的异常→JSON 兜底。
|
||
*
|
||
* 用法(endpoint 顶部):
|
||
* require_once __DIR__ . '/../common/Api.php';
|
||
* $pdo = Api::boot(['module' => 'preliminary']); // 登录 + 模块权限(写接口另含 Ajax/CSRF)
|
||
* $pdo = Api::boot(); // 仅要求登录(如 session.php)
|
||
* $pdo = Api::boot(['super' => true]); // 仅超级管理员
|
||
* $pdo = Api::boot(['permissions' => [...]]); // 任一权限
|
||
* $pdo = Api::boot(['public' => true]); // 免登录(仅 login/forgot/csrf)
|
||
*
|
||
* boot() 统一执行:
|
||
* - 安全 Session(httponly/samesite)
|
||
* - POST/PUT/PATCH/DELETE:checkAjax(X-Requested-With)+ checkCsrf(Token 头)
|
||
* - 登录态 + 权限
|
||
* - 返回 PDO(后续代码可直接用 $pdo;原 `$pdo = DB::getInstance()->getPdo();`
|
||
* 属冗余无害,可保留)
|
||
*
|
||
* 本文件另注册全局异常处理器:未捕获异常统一转 JSON 500 + 技术日志。
|
||
*/
|
||
require_once __DIR__ . '/db.php';
|
||
require_once __DIR__ . '/response.php';
|
||
require_once __DIR__ . '/logger.php';
|
||
require_once __DIR__ . '/security.php';
|
||
require_once __DIR__ . '/auth.php';
|
||
require_once __DIR__ . '/helpers.php';
|
||
require_once __DIR__ . '/validate.php';
|
||
require_once __DIR__ . '/duplicate_check.php';
|
||
require_once __DIR__ . '/completeness.php';
|
||
|
||
/** 统一异常处理:未捕获异常 → JSON 500 + 技术日志(REV-ARCH-3) */
|
||
set_exception_handler(function (\Throwable $e) {
|
||
logError('未捕获异常', [
|
||
'msg' => $e->getMessage(),
|
||
'file' => $e->getFile(),
|
||
'line' => $e->getLine(),
|
||
'uri' => $_SERVER['REQUEST_URI'] ?? '',
|
||
]);
|
||
if (!headers_sent()) {
|
||
http_response_code(500);
|
||
header('Content-Type: application/json; charset=utf-8');
|
||
}
|
||
echo json_encode(['code' => 500, 'msg' => '服务器内部错误,请稍后重试'], JSON_UNESCAPED_UNICODE);
|
||
exit;
|
||
});
|
||
|
||
class Api
|
||
{
|
||
/**
|
||
* 统一引导
|
||
* @param array $opts 见文件头注释
|
||
* @return PDO
|
||
*/
|
||
public static function boot(array $opts = [])
|
||
{
|
||
startSessionSecure();
|
||
|
||
$isWrite = in_array($_SERVER['REQUEST_METHOD'] ?? 'GET', ['POST', 'PUT', 'PATCH', 'DELETE'], true);
|
||
if ($isWrite) {
|
||
checkAjax();
|
||
}
|
||
|
||
if (empty($opts['public'])) {
|
||
if (!empty($opts['super'])) {
|
||
requireSuperAdmin();
|
||
} elseif (!empty($opts['module'])) {
|
||
checkPermission($opts['module']);
|
||
} elseif (!empty($opts['permissions'])) {
|
||
checkAnyPermission($opts['permissions']);
|
||
} else {
|
||
requireLogin();
|
||
}
|
||
}
|
||
|
||
if ($isWrite) {
|
||
checkCsrf();
|
||
}
|
||
|
||
return DB::getInstance()->getPdo();
|
||
}
|
||
}
|