Files
cursor/plans/php用例写法规则_01c4ae1f.plan.md
ray zhou f71a5c59af ok
2026-05-29 11:21:40 +08:00

228 lines
10 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

---
name: PHP用例写法规则
overview: 在用户级 Cursor 新增 `php-use-case-style.mdc`,约束 slot 后端所有 PHP 业务代码Controller/Logic/Service/Model/Command 等)的表达力与可维护性;并扩展 verify-slot-backend.sh 对 diff 中所有 touched 的 app/**/*.php 做轻量检查。仅约束本次 diff不强制全盘重构历史代码。
todos:
- id: create-mdc
content: 创建 ~/.cursor/rules/php-use-case-style.mdc全层 MUST/禁止、BAD/GOOD、按层对照表
status: completed
- id: update-gate-rule
content: 在 agent-completion-gate.mdc 增加对 php-use-case-style 的引用(任意 PHP 改动)
status: completed
- id: extend-verify
content: 扩展 verify-slot-backend.sh所有 app/**/*.php diff 检查 + @use-case-exempt
status: completed
- id: smoke-verify
content: 分别在 Logic/Controller/Service diff 触发自测 PASS/FAIL/豁免
status: completed
- id: merge-php-code
content: 用例写法合并进 php-code.mdc修 frontmatter/强制要求/命名
status: completed
- id: fix-gate-refs
content: agent-completion-gate 引用改为 php-code
status: completed
- id: smoke-rules
content: 确认规则生效 + verify PASS
status: completed
isProject: false
---
# PHP 代码写法规则 + Verify 门禁(全层)
## 目标
让 AI 在改 **任意 slot 后端 PHP 业务代码** 时默认产出:**编排清晰、职责单一、业务异常语义正确、状态变更有条件更新与幂等键**,并对齐仓库内参照实现。
适用范围(规则 + verify 一致):
- `app/api/controller/**`
- `app/api/logic/**``app/innerapi/logic/**``app/napi/logic/**`
- `app/service/**`
- `app/model/**`
- `app/command/**`
- 其它 `app/**` 下业务 PHP`validate``entity` 等按条适用)
**不覆盖**`vendor/``tests/`(除非 diff 触及且单独约定)、纯配置/SQL 文件。
## 默认范围
- **规则文件**:用户级 [`~/.cursor/rules/php-use-case-style.mdc`](~/.cursor/rules/php-use-case-style.mdc)
- **生效方式**`alwaysApply: true`(任意对话均注入;与 `backend-layering` 同级,避免只开 Logic 文件时漏规则)
- **门禁脚本**[`~/.cursor/hooks/verify-slot-backend.sh`](~/.cursor/hooks/verify-slot-backend.sh)(仅 `git diff` + 路径 `app/`
- **不在本阶段**:强制重构历史代码(如 `DailyRebateLogic::claim`);可另开样板 PR
## 1. 新增规则 `php-use-case-style.mdc`
**Frontmatter**
```yaml
---
description: Slot PHP 写法——表达力、可维护、全层通用Controller/Logic/Service/Model/Command
alwaysApply: true
---
```
### 1.1 全层通用 MUST
| 条目 | 要求 |
|------|------|
| 单一职责 | 一个 public 方法只做一件事;编排方法目标 ≤25 行,超出拆 private |
| if 墙 | 禁止同一方法内连续 ≥4 个 `if (...) throw/return error`;合并为 `assert*` / `ensure*` |
| 业务异常 | 可预期业务失败用 `support\exception\BusinessException`;禁止用 `RuntimeException` 表示业务态(未开启、不可领、已过期等) |
| 魔法值 | 状态/类型用 Model 常量或 enum禁止裸 `1/2/3` 散落diff 新增代码) |
| 命名 | 方法名表达意图(`assertClaimable``markClaimedIfClaimable`),禁止 `doClaim``handle` 等空泛名(新增代码) |
| 参照 | 领取/入账编排:[`FreeCreditsLogic::claim`](slot_console/app/api/logic/FreeCreditsLogic.php)Controller[`FreeCreditsController`](slot_console/app/api/controller/FreeCreditsController.php) |
### 1.2 按层补充(与 backend-layering 互补,不重复分层表)
| 分层 | 写法 MUST | 禁止 |
|------|-----------|------|
| **Controller** | 仅Validate → 调 Logic/Service → `success/errorCode``catch BusinessException` 映射业务码 | 业务 if 墙、直接 `Db::`、直接 `gift()` |
| **Logic** | 用例编排:`buildContext``assert*``perform*``format*`;事务边界在此 | 纯转发 Model 无编排、跨服务裸 curl |
| **Service** | 可复用能力封装外部系统wallet/sdk隔离稳定 `biz_id` | Logic 型 Service单用例整条流水线 |
| **Model** | 查询/写入 + `scope`/`mark*If*` 条件更新;金额字段注释单位(厘) | 业务编排、调 Wallet |
| **Command** | 薄入口:参数解析 → 调 Logic日志 phase 结构化 | 复制 Logic 大段 if 墙 |
| **Validate** | 格式/必填/枚举 | 业务规则(「是否可领」应在 Logic assert |
### 1.3 领取 / 入账 / 状态变更(凡涉及处均适用)
- MUST条件更新`where status = expected``update`),鼓励 Model 方法 `mark*If*`
- MUST钱包/外部入账带稳定 `biz_id`(如 `daily_rebate:{uid}:{statDate}`
- Controller禁止 `catch (\RuntimeException)` 后一律 `PARAMS_ERROR`
### 1.4 BAD / GOOD规则内各一段≤8 行)
- BADController `catch RuntimeException` + Logic 5 连 throw + Service 仅 `return Model::find()`
- GOODController 捕 `BusinessException`Logic `assert*` + 条件更新Service 封装 wallet + biz_id
### 1.5 与现有规则关系
- 分层职责:仍服从 [`backend-layering.mdc`](~/.cursor/rules/backend-layering.mdc)
- 文档:仍服从 [`php-doc.mdc`](~/.cursor/rules/php-doc.mdc)
- [`agent-completion-gate.mdc`](~/.cursor/rules/agent-completion-gate.mdc) 增加:**任意改动 `app/**/*.php` 须遵守 `php-use-case-style`**
## 2. 扩展 `verify-slot-backend.sh`
**`CHANGED_PHP` 且路径匹配 `*/app/*`** 的文件检查(不再限定 `/logic/`
```bash
# 1) diff 新增行含 throw new \RuntimeException业务态误用
# 豁免:文件含 @use-case-exempt
# 2) Controller*/app/**/controller/*diff 新增行:
# catch (\RuntimeException 且同文件/邻近行 PARAMS_ERROR → fail
# 3) 已有BaseController、banlist、deleted class — 保持不变
```
**原则**
- 只 FAIL **diff 新增行**`git diff -U0` / `git diff --cached -U0`),不扫历史行
- `@use-case-exempt` 在文件前 5 行内则跳过该文件全部 use-case 检查
- 首期不 FAIL方法行数、biz_id 参数名(写在规则 MUSTverify 二期)
## 3. 数据流
```mermaid
flowchart TB
subgraph agent [Agent 改任意 app PHP]
rule[php-use-case-style alwaysApply]
layers[Controller Logic Service Model Command]
end
subgraph gate [完成前]
verify[verify-slot-backend app/** diff]
hook[stop hook followup]
end
rule --> layers
layers --> verify
verify -->|FAIL| hook
verify -->|PASS| done[可声称完成]
```
## 4. 验收
1. 打开任意 `app/service/*.php``DailyRebateController.php`规则均应生效alwaysApply
2. 在 Controller diff 新增 `catch (\RuntimeException` + `PARAMS_ERROR` → verify FAIL
3. 在 Service diff 新增 `throw new \RuntimeException('活动未开')` → verify FAIL
4.`@use-case-exempt` → 该文件跳过
5. `~/.cursor/hooks/verify-slot-backend.sh` 输出 PASS
## 5. 后续可选(本计划不含)
- 样板 PR重构 `DailyRebateLogic::claim` + `DailyRebateController::claim`
- verify 二期:`gift(` / wallet 调用邻近 biz_id 检测public 方法行数 WARN
---
## 6. 阶段二:合并进 `php-code.mdc`(待执行)
用户已将 PHPDoc 并入 [`php-code.mdc`](~/.cursor/rules/php-code.mdc)`php-use-case-style.mdc` 已不存在。verify 已具备 use-case 检查,但规则与 gate 引用断裂。本阶段只做规则对齐,不改业务代码。
### 6.1 修改 `php-code.mdc`
**Frontmatter**(删空 `globs:`
```yaml
---
description: PHP 全局工程规范PHPDoc + 用例写法 + AI 纪律)
alwaysApply: true
---
```
**在「代码原则」后插入新章节「用例写法app/**)」**(约 35 行):
- MUST业务失败 `support\exception\BusinessException`;禁止 `RuntimeException` 表业务态
- MUST编排 public 方法 ≤25 行;同一方法禁止连续 ≥4 个 `if (...) throw` → 抽 `assert*`
- MUST状态变更条件更新钱包入账稳定 `biz_id``daily_rebate:{uid}:{date}`
- 按层表(与 backend-layering 互补Controller 禁止业务 if 墙 / 直接 giftLogic 编排结构;禁止 Logic 型 Service
- 参照:`slot_console/app/api/logic/FreeCreditsLogic.php` :: `claim()``FreeCreditsController.php`
- BAD/GOOD 各一段RuntimeException vs BusinessExceptionController catch
- 豁免:文件前 5 行 `@use-case-exempt`(与 verify 一致)
**改写「强制要求」**L8492为 diff 范围:
```markdown
## 强制要求(本次 diff 新增/修改须符合)
- PHP 8+;新增/修改的方法须有 typed parameter 与 return
- 新增类属性须 typed property
- 新建文件或本次 diff 触及的文件顶部可加 `declare(strict_types=1);`,禁止为达标改无关历史文件
```
**微调「命名规范」**
- 禁止 `$tmp``$a``$b`、无业务含义的 `$data`/`$list`
- **删除** blanket 禁止 `$info`(与 `UserInfoEntity` 等冲突);改为禁止「无上下文的 `$info` 临时变量」
**文末增加「与 verify 对齐」**
- diff 新增 `throw new RuntimeException`(业务态)→ verify FAIL
- Controller diff 新增 `catch RuntimeException` + `PARAMS_ERROR` → verify FAIL
### 6.2 修改 `agent-completion-gate.mdc`
```diff
- 3. 修改 PHP 后,最终回复含 `PHPDoc: checked`(见 php-doc 规则)。
- 4. 改动 `app/**/*.php` 须遵守 `php-use-case-style`表达力、BusinessException、按层写法
+ 3. 修改 PHP 后,最终回复含 `PHPDoc: checked`(见 php-code 规则 PHPDoc 章节)。
+ 4. 改动 `app/**/*.php` 须遵守 `php-code` 用例写法章节BusinessException、按层写法
```
### 6.3 不改动
- `verify-slot-backend.sh`(已含 use-case 检查)
- `backend-layering.mdc``cross-service-sdk.mdc`
### 6.4 验收
1. `~/.cursor/rules/` 仅一份 PHP 总规范 `php-code.mdc`,无悬空 `php-doc` / `php-use-case-style` 引用
2. 新开 Agent 对话,改 `app/**` PHP 时应看到用例写法 + PHPDoc
3. `~/.cursor/hooks/verify-slot-backend.sh` → PASS
### 6.5 执行 todos
| id | 内容 |
|----|------|
| merge-php-code | 按 6.1 更新 php-code.mdc |
| fix-gate-refs | 按 6.2 更新 agent-completion-gate.mdc |
| smoke-rules | 打开 DailyRebateLogic + 跑 verify |