first commit

This commit is contained in:
ray zhou
2026-05-21 18:16:26 +08:00
commit 033aa0ae69
324 changed files with 24705 additions and 0 deletions

View File

@@ -0,0 +1,22 @@
---
description: Backend layering responsibilities and Logic-Service boundaries
alwaysApply: true
---
# Backend Layering Rules
| 分层 | 职责 |
| --- | --- |
| **Controller** | 接收请求;补充 header / 路由参数;调用 Validate构建 DTO调用 Logic / Service返回统一响应 |
| **Validate** | 参数必填、类型、长度、格式、枚举、数组结构 |
| **DTO** | 承载已校验参数;做轻量格式整理;**不**做参数合法性判断;**不**查数据库;**不**写业务规则 |
| **Logic** | 负责业务用例、流程编排、事务控制;可以调用本 Logic 内部方法组织步骤;简单逻辑可直接调用 Model复杂或跨场景复用能力才调用 Service |
| **Service** | 只承载公共能力,例如 center / sdk / 公共配置 / 公共计算 / 跨业务复用逻辑;**不是**每张表都建一个 Service**不是**把 Logic 方法简单搬过去 |
| **Model** | 数据查询数据写入scope / 搜索器 / 关联;把查询条件沉淀成模型方法 |
## Logic 与 Service 边界
- Logic 可以调用自己的私有方法或内部方法,用于拆分步骤、复用当前业务用例内的流程片段。
- 只有当某段能力具备跨场景复用价值、公共计算价值、公共配置访问、外部系统封装等公共属性时,才应抽到 Service。
- 不应创建只做中转的 Service 方法,例如 Logic 调用 ServiceService 再原样调用 Model 或另一个 Logic且没有封装公共能力。
- 如果确实需要中转层,必须在代码或 PR 说明中解释原因,例如兼容历史接口、统一事务边界、隔离第三方 SDK、收敛跨模块依赖等。

View File

@@ -0,0 +1,55 @@
---
description: 跨服务 HTTP 须经 slot_sdkslot/sdk调用禁止在业务服务内散落直连
alwaysApply: true
---
# 跨服务通信slot_sdk
**slot_sdk** 是跨服务 HTTP 客户端库(`composer` 包 `slot/sdk`,命名空间 `slotsdk\`),用于**调用方服务**访问**被调服务**的 `innerapi/*` 或 `api/*` 接口。它不是独立部署的微服务。
术语:说「**跨服务 HTTP 调用**」「**经 slot_sdk 调用**」,不说「服务间中转」或「通过 slot/sdk 中转」(库是客户端,被调服务仍直接处理请求)。
## 适用范围
- 一个 Webman 服务需要 HTTP 访问另一个服务的 `innerapi` / `api` 时,**调用方**必须通过 slot_sdk。
- **被调服务**实现 Controller / Logic / Model**不**为「被别人调」而引入 `slot/sdk`。
- **调用方**若需访问第三个服务,禁止在业务代码里手写 Guzzle/curl 或拼接 `host + path`。
## 标准调用方式
```php
use slotsdk\Config as SDKConfig;
use slotsdk\service\wallet\WalletClient;
$config = new SDKConfig([
'host' => ShareConfigService::get('walletApiHost'),
'headers' => ['server-name' => config('app.server_name')],
]);
$result = (new WalletClient($config))->service()->getStatistics($uids, $currency);
```
- 调用链:`new {Domain}Client($config)->service()->{method}(...)`
- Host 来自 center 下发的 `*ApiHost`(如 `walletApiHost`、`userApiHost`)。
- 请求头 `server-name` 为**当前调用方**服务名。
- 响应 `code !== 0` 时抛出 `slotsdk\exception\ApiException`,在 Logic 或 Gateway 层处理。
## 新增 / 变更远程接口
1. 先在 `slot_sdk/src/service/{domain}/` 增加 `{Domain}Service` 方法、路径、必要时 `entity/*Entity`。
2. 再在调用方 Logic 或 `*GatewayService` 中调用Controller 保持薄。
3. **禁止**在 `slot_admin`、`slot_agent` 等多仓库重复写同一路径字符串。
## 与单服务分层的关系
跨服务访问落在调用方的 **Service** 或 **`*GatewayService`**Logic 编排用例HTTP 细节不散落在 Controller。与 [backend-layering](backend-layering.mdc) 中「Service 可承载 sdk」一致分层职责见该规则此处只约束**跨服务边界**。
## 命名与混淆规避
| 类型 | 约定 |
| --- | --- |
| SDK 客户端 | `slotsdk\service\{domain}\{Domain}Client` |
| SDK 方法类 | `slotsdk\service\{domain}\{Domain}Service` |
| SDK DTO | `entity\{Name}Entity`、`{Name}RequestEntity` |
| 本地服务 | `app\service\*`(本地 WalletService ≠ slotsdk WalletService |
同名时:`use slotsdk\Config as SDKConfig` 或完整 namespace。消费方对重复跨服务调用可封装为 `*GatewayService`(如 `UserReferralGatewayService`)。

42
rules/dev-environment.mdc Normal file
View File

@@ -0,0 +1,42 @@
---
description: Slot 本地 Docker 开发环境PHP / MySQL / Redis
alwaysApply: true
---
# Local Dev (Docker)
PHP、MySQL、Redis 均在 Docker 中运行;**不要在 macOS 宿主机**直接执行 `php` / `composer`(除非已确认本机版本与项目一致)。
## Compose 与挂载
- Compose`/Users/ray/Documents/project/docker/docker-compose.yml`
- 宿主机项目根:`/Users/ray/Documents/project` → 容器内 `/app`
- Slot 服务路径:`/app/www/slot/<repo>`(如 `slot_wallet`、`slot_user`、`backend/slot_admin`
## 容器与端口
| 服务 | 容器名 | 宿主机端口 |
| --- | --- | --- |
| PHP 8.2(默认) | `php82` | — |
| MySQL 8 | `goMysql` | `3309` → 容器 `3306` |
| Redis | `redis` | `6379` |
| Go Redis | `goredis` | `6378` → 容器 `6379` |
凭据以 `docker-compose.yml` 为准。
## 执行命令
默认在 `php82` 内、对应服务目录执行Webman 项目无 `artisan`
```bash
docker exec -w /app/www/slot/slot_wallet php82 php webman <command>
docker exec -w /app/www/slot/slot_wallet php82 composer install
```
MySQL CLI容器内
```bash
docker exec -it goMysql mysql -uroot -p
```
从宿主机连接:`127.0.0.1:3309`MySQL、`127.0.0.1:6379`Redis

60
rules/php-doc.mdc Normal file
View File

@@ -0,0 +1,60 @@
---
description: "Use this rule whenever creating or modifying PHP files. Enforce PHPDoc for changed classes, interfaces, traits, enums, methods, class constants, and newly added properties."
globs:
- "slot_*/**/*.php"
- "backend/**/*.php"
alwaysApply: false
---
# PHP PHPDoc 规范(严格)
## 适用范围
- 新增或修改的 PHP 文件中的:
- class / interface / trait / enum
- 所有方法public / protected / private
- 所有类常量const
- 新增属性
- 只处理本次 diff 触及的符号
- 不追溯未改动的历史代码
- 但本次 diff 触及的符号若缺 PHPDoc必须一并补齐
## 最低 PHPDoc 内容
| 符号 | 必须包含 |
| --- | --- |
| 类 / 接口 / Trait / Enum | 一行职责说明 |
| 方法 | 职责说明 + 每个参数的 `@param` + `@return`;有 `throw` 的须 `@throws` |
| 类常量 | 一行说明业务含义:单位、枚举语义、与配置/表字段对应关系 |
| 属性 | typed property + 一行说明;类型不直观时加 `@var` |
已有 PHP 8+ 类型声明时,`@param` / `@return` 仍须保留。
## 禁止项
- 禁止空 `/** */`
- 禁止无 `@param` / `@return` 的方法 PHPDoc
- 禁止 `@param int $id id` 式同义反复
- 禁止用 PHPDoc 替代 Validate / Logic 里的业务校验说明
- 禁止为显而易见语句写冗长注释
## 分层补充
| 分层 | PHPDoc 额外要求 |
| --- | --- |
| Controller | 接口用途;幂等/鉴权前提 |
| Logic | 用例步骤;事务边界;失败时行为 |
| Service | 复用场景;调用方约束 |
| Model | 查询条件;分表键;金额字段单位 |
| DTO / Validate | 字段含义;与上游参数映射 |
## Agent 执行要求
修改 PHP 文件后,必须检查本次 diff
1. 每个新增或修改的 class / interface / trait / enum 是否有 PHPDoc
2. 每个新增或修改的方法是否有职责说明、`@param`、`@return`
3. 每个新增或修改的类常量是否有业务含义说明
4. 新增属性是否有 typed property 和说明
5. 不要为了补 PHPDoc 改动无关历史代码
6. 最终回复中说明PHPDoc 检查已完成,若有例外必须列出原因