Files
cursor/rules/php-clean-code.mdc
ray zhou f71a5c59af ok
2026-05-29 11:21:40 +08:00

218 lines
6.7 KiB
Plaintext
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.

---
description: PHP clean code rules for readable, maintainable and clear backend code
globs:
- "**/*.php"
alwaysApply: true
---
# PHP Clean Code Rules
目标:生成和修改 PHP 后端代码时,优先保证 **可读、可维护、清晰、简单、易排查**。
分层职责遵循 `Backend Layering Rules`。本规则只约束代码写法质量。
---
## 1. 核心原则
- 优先清晰,不写炫技代码。
- 一个方法只表达一个明确动作。
- 代码应像业务流程一样容易阅读。
- 复杂逻辑必须拆成有业务语义的私有方法。
- 不要为了减少行数牺牲可读性。
- 不允许用注释弥补糟糕命名。
- 禁止无意义的 `Helper`、`Util`、`CommonService`、`Manager`。
- 禁止创建只做转发、没有业务价值的中间层。
---
## 2. 命名规则
禁止用模糊变量名承载核心业务数据:
- `$data`
- `$list`
- `$info`
- `$tmp`
- `$row`
- `$result`
- `$res`
- `$arr`
变量、方法、类名必须表达业务含义。
推荐命名风格:
- `$userInfo`
- `$rebateConfig`
- `$walletTransaction`
- `$validBetAmount`
- `$claimResult`
- `getEnabledUser()`
- `ensureCanClaim()`
- `createWalletTransaction()`
- `claimRebateInTransaction()`
布尔变量必须表达真假语义,例如 `$isEnabled`、`$isClaimed`、`$hasPermission`、`$canWithdraw`。
避免无意义方法名:`handle()`、`process()`、`doSomething()`、`getData()`、`getList()`。
如果必须使用 `handle()` / `process()`,需要有明确上下文,例如 `handlePaymentCallback()`、`processSettledBet()`。
---
## 3. 方法规则
- 方法长度建议不超过 50 行。
- 方法嵌套不超过 3 层。
- 优先使用 early return / early throw。
- 方法参数一般不超过 3 个。
- 参数超过 3 个时,优先使用 DTO、Value Object 或专门数据结构。
- 核心业务入参不要直接使用含糊的 `array`。
- 返回 `array` 时必须结构明确,并用 PHPDoc 描述结构。
- 私有方法也必须有清晰业务语义。
- 复杂条件必须封装成有语义的方法。
- 魔法数字必须变成常量或枚举。
- 业务规则判断优先使用 `ensureXxx()` 方法。
- 不要把查询、判断、写入、返回组装全部堆在一个大方法里。
---
## 4. Logic / Service / Model 写法
### Logic
- Logic 是业务用例入口,一个 public 方法通常对应一个业务用例。
- Logic 主方法要像读业务流程。
- Logic 私有方法必须有业务语义。
- Logic 可以查业务主体、调用 Model、调用公共 Service、做业务判断、控制事务、写业务日志、组装返回结果。
- 复杂查询条件应沉淀到 Model。
- 涉及多表写入、钱包变动、订单状态变更、活动领取、返水领取、游戏下注 / 派奖时,事务边界必须放在 Logic。
- 事务内禁止请求第三方接口、发送 MQ、发送短信、发送邮件、大量循环处理、复杂远程调用。
### Service
- Service 只放公共能力,例如第三方 SDK、center 调用、公共配置、公共计算、跨业务复用逻辑、基础设施封装。
- Service 禁止承载单业务用例编排。
- Service 禁止只做 Model 转发或 Logic 转发。
- Service 禁止为每张表创建一个 Service。
- 如果一个 Service 方法没有封装公共能力,不应创建。
### Model
- Model 负责数据查询和写入。
- Model 可以包含查询条件封装、scope、搜索器、关联关系、简单数据写入、常用查询方法。
- Model 禁止写复杂业务流程、控制事务、调用第三方接口、编排多个业务步骤。
- Model 方法命名必须表达查询或写入意图,例如 `findEnabledById()`、`existsClaimedRecord()`、`sumValidBetAmount()`、`createClaimRecord()`。
- 避免 `getData()`、`getList()`、`handle()`、`process()`。
---
## 5. PHPDoc 与注释
Logic、Service、Model 的 public 方法建议写 PHPDoc。
以下情况必须写 PHPDoc
- 返回 `array`
- 参数是复杂 `array`
- 可能抛出业务异常
- 涉及状态流转
- 涉及钱包、订单、活动、游戏交易
- 方法语义不是一眼能看懂
返回 array 必须写结构:
```php
/**
* @return array{
* user_id: int,
* nickname: string,
* balance: int
* }
*/
```
复杂 array 参数必须写结构:
```php
/**
* @param array{
* user_id: int,
* amount: int,
* order_no: string,
* remark?: string
* } $data
*/
```
涉及异常必须写 `@throws`。
不要写废话 PHPDoc。简单 getter/setter、方法名和类型已足够清晰时不强制 PHPDoc。
注释解释为什么,不解释做什么。复杂业务、幂等处理、分布式锁、状态流转、第三方接口兼容、历史兼容逻辑必须有注释。
---
## 6. 异常、日志、返回
- 禁止返回 `false` 表示业务失败。
- 业务失败应抛出业务异常。
- 禁止吞异常。
- 捕获异常后必须记录必要上下文;如无法处理,必须继续抛出。
- 业务异常和系统异常要区分。
- 异常信息必须清晰,不能只写 `error`、`failed`。
- 关键业务必须打日志,例如钱包变动、游戏下注、游戏派奖、支付回调、活动领取、返水领取、第三方接口异常、风控命中、重要状态变更。
- 日志必须包含关键上下文,例如 `user_id`、`order_no`、`provider_code`、`provider_tx_id`、`round_id`、`amount`、`status`、`error`。
- 日志禁止记录密码、token、secret、私钥、支付密钥、银行卡完整号码、用户隐私数据、第三方签名密钥。
- 返回结构必须明确。
- 不直接返回 Model 对象。
- 不返回临时调试字段、SQL、异常堆栈、内部配置、secret、token、sign。
---
## 7. 幂等要求
涉及重复请求风险必须考虑幂等包括第三方回调、钱包加减款、订单支付、活动领取、返水领取、游戏下注、游戏派奖、MQ 消费。
优先使用唯一索引保证幂等,并在代码中保留明确幂等判断。
---
## 8. Agent 自查
完成代码前必须自查:
- 命名是否清晰?
- 方法是否过长?
- 嵌套是否过深?
- 是否有魔法数字或魔法字符串?
- Logic 是否表达清晰业务流程?
- Service 是否确实是公共能力?
- Model 是否只做数据访问?
- 多表写入是否有事务?
- 是否需要幂等?
- 是否吞异常?
- 日志是否有关键上下文?
- 是否泄露敏感信息?
- 返回数据是否明确?
- 是否直接返回 Model
- 返回 array 的方法是否写清楚 PHPDoc
- 复杂数组参数是否写清楚 PHPDoc
- 涉及异常的方法是否写了 `@throws`
---
## 9. 优先级
当规则冲突时,按以下优先级处理:
1. 正确性
2. 安全性
3. 数据一致性
4. 可读性
5. 可维护性
6. 简洁性
7. 性能
除非已有明确性能瓶颈,否则不要为了性能牺牲可读性。