Skip to content

PHP 后端基础规范(API 服务)

1. 适用范围

本规范约束仓库内 PHP HTTP API 服务 的代码组织方式,当前落地目录为 services/api/。其它语言服务、仅文档/脚本不在此列。

与全局协作规则的关系:先遵守 AGENTS.mddocs/standards/开发规范.md,再遵守本文件;若本文件与架构文档冲突,以架构文档与任务文档为准并显式记录冲突。


2. 分层与职责(强制)

层次位置(约定)职责
路由services/api/router/api.php(由 public/index.php 加载)仅声明 HTTP 方法、路径、控制器类与方法;不写业务逻辑。
控制器services/api/app/Controllers/解析请求、调用下层、组装 HTTP 响应;保持薄,不写复杂领域规则。
数据访问services/api/app/Repositories/封装对数据库、缓存、外部 HTTP 等 事实读写的边界;不承载业务流程编排。
业务逻辑services/api/app/Logic/(可按域分子目录,如 Logic/Api/多步编排、跨 Repository、复杂校验、可复用领域过程 放在此处;入口鉴权类 App\Logic\Auth 亦属本层。
公共函数services/api/app/helper.php(Composer autoload.files 已加载)多处复用、与框架无关的纯函数或小工具(如解析请求头、格式化);避免把业务流程堆进 helper。
框架/基础设施services/api/lib/请求/响应、路由、异常、缓存等 与业务无关 的通用能力。

3. 新增接口的强制顺序

  1. router/api.php 注册路由Route::get/post/...),路径与 Lib\Route 的 URI 规则一致(注意 Route::group 前缀,完整路径形如 api/...)。
  2. 实现或扩展控制器(通常 App\Controllers\Api\*)。
  3. 需要持久化或外部数据时,在 Repositories 增加或复用方法,由 Logic 或控制器调用。
  4. 当单接口内分支多、步骤多、或两处以上控制器要复用同一套规则时,将过程抽到 Logic(必要时拆类),控制器只保留一行或数行调用。
  5. 当同一纯逻辑在多个类/层出现(例如解析 Authorization: Bearer),抽到 helper.php 或小的 Logic 辅助类,禁止复制粘贴

4. 控制器书写约定

  • 简单逻辑(参数读取、一次 Repository 调用、固定 JSON 形状)可直接写在控制器方法内。
  • 复杂逻辑必须下沉到 Logic,控制器仅负责:jsonBody() / getAttr / 调用 Logic、返回 Response 或数组。
  • 需登录的 JSON API 可复用 App\Controllers\Api\Concerns\JsonApiTrait(如 handleJsonActionrequirePortalAccount)。
  • 禁止在控制器中直接写 SQL;禁止在 Repository 中写与 HTTP 强耦合的代码。

5. 鉴权与用户上下文(强制)

  • 统一入口:需鉴权的 API 控制器应继承 App\Controllers\BaseApiController,在 beforeHook() 中通过 App\Logic\Auth::check() 完成校验;未通过则 abort401(),不进入 Action。
  • 白名单:免登录路径在 BaseApiController$withoutAuth 中维护,值为 去掉前导 / 的路径(与 Request::$uri 对齐),例如 api/auth/login
  • 鉴权结果写入 RequestAuth 校验成功后通过 Request::setAttr() 注入,控制器与 Logic 通过 Request::getAttr() 读取,禁止在业务控制器构造函数中重复组装一套“只为取当前用户”的会话对象。
  • 约定键名(与 JSON body 共用存储,勿与客户端字段冲突):
    • App\Logic\Auth::ATTR_USER_ID:当前用户主键(Legacy Token 与门户均可能写入)。
    • App\Logic\Auth::ATTR_PORTAL_ACCOUNT:门户登录后的 账号表行array);控制器侧可使用 JsonApiTrait::requirePortalAccount()
  • Legacy 与门户并存时,以 Auth::check() 的实现为准(例如先 Token 头 / token 查询参数,再 Authorization: Bearer);新增方式应扩展 Auth,而不是在控制器里平行判断。

6. helper.php 使用原则

  • 适合:无状态字符串/数组处理、可单元测试的解析函数、与具体业务表无关的通用工具(如 parse_authorization_bearer())。
  • 不适合:依赖大量全局状态、长业务流程、仅单接口使用一次的代码(留在控制器或 Logic 即可)。

7. 自检清单(提交前)

  • [ ] 新接口是否已出现在 router/api.php
  • [ ] 是否避免在 Repository 外直接访问数据库连接?
  • [ ] 复杂逻辑是否已从控制器挪到 Logic
  • [ ] 多处重复的片段是否已抽到 helper 或 Logic?
  • [ ] 需登录接口是否继承 BaseApiController,且未在 Action 内重复鉴权?
  • [ ] 写入 Request 的内部键是否使用 Auth 常量或团队约定前缀,避免与 body 字段撞名?

8. 变更与回写

修改本规范约定的目录职责或鉴权链时,应同步检查:

  • services/api/README.md(若存在服务级说明)
  • changelogs/ 中相关条目
  • 任务文档中的验收说明

9. 版本说明

  • 2026-04:初版,与当前 services/api 路由、基类鉴权、Auth + Request 注入方式对齐。