# Hyperf Framework

> PHP 8.1+ 与 Hyperf 3.1 协程微服务架构通用开发与工程规范技能。 涵盖 Controller->DTO->Service->Repository 四层分层架构标准、Swoole 协程常驻内存安全红线 (Hyperf\Context\Context)、 PHP 8 Attribute 原生注解规范、HTTP 路由与参数约定 (禁 URL Path 业务参数)、 数据库事务边界与 N+1 查询杜绝、异步队列幂等与多实例 Crontab 分布式锁防护。

- Skill: `garfield247/hyperf-framework` (Agent Skill, multi-file: 4 files)
- Install (CLI): `npx skillmds@latest add garfield247/hyperf-framework`
- Raw SKILL.md: https://api.skillmd.com/api/skills/garfield247/hyperf-framework/raw
- Safety review: pending
- Works with: Claude Code, Claude.ai, OpenAI Codex
- Category: Coding & Dev Tools
- Author: Garfield247 (https://skillmd.com/u/garfield247)
- Updated: 2026-09-22
- Page: https://skillmd.com/skills/garfield247/hyperf-framework

---


# PHP 8.1+ & Hyperf 3.1 协程架构开发规范技能 (Hyperf Framework Mastery)

## 概述 (Overview)

本技能定义了基于 **PHP 8.1+ 与 Hyperf 3.1（Swoole 协程引擎）** 进行高性能后端微服务开发的专属规范、分层架构与工程红线。
聚焦于 **“四层分层清晰、协程状态隔离、强类型 DTO 校验、防 N+1 查询与消费幂等闭环”**，彻底剔除与框架无关的通用冗余规则，专注于 Hyperf 与 Swoole 协程环境的生产级工程实践。

---

# 1. 架构分层与职责边界 (Architecture Layers)

Hyperf 工程必须严格遵循 **`Controller → DTO → Service → Repository`** 四层分层体系，严禁跨层调用与职责错位：

```mermaid
graph TD
    Client["客户端请求"] --> Controller["Controller (HTTP/RPC 传输控制层)<br/>• 路由映射与中间件调度<br/>• 触发 DTO 自动校验<br/>• 统一响应封装 (code/msg/data)"]
    Controller --> DTO["DTO (数据传输契约对象)<br/>• 强类型入参绑定与范围校验<br/>• 严禁任何数据库/网络 I/O"]
    Controller --> Service["Service (领域业务与事务层)<br/>• 业务用例编排与规则计算<br/>• 事务边界控制 (Db::transaction)<br/>• 隔离传输层，不向底层泄漏 Request/Response"]
    Service --> Repository["Repository (数据持久化与缓存层)<br/>• 屏蔽 SQL / GORM / Redis 访问细节<br/>• 复杂多表联合聚合查询<br/>• 不负责 HTTP 状态码与响应组装"]
```

### 1.1 各层职责与禁止红线

| 架构分层 | 核心职责 | 🚨 严厉禁止红线 |
| :--- | :--- | :--- |
| **Controller** | 路由 Mapping 声明、鉴权中间件触发、调用 Service、统一输出结构 | 严禁直接编写 SQL 查询、Redis 缓存读写或核心业务逻辑编排 |
| **DTO** | 强类型数据绑定、字段类型转换、业务范围与格式校验规则 | 严禁执行任何数据库、Redis、HTTP、MQ 等网络或存储 I/O 操作 |
| **Service** | 业务用例编排、业务状态机推进、分布式锁协同、事务边界控制 | 严禁直接读取 HTTP `Request` 对象或处理前端展示格式 |
| **Repository** | 封装 Model 查询、SQL 优化、Redis 缓存维护与批量数据读写 | 严禁包含 HTTP 响应组装逻辑，严禁处理非存储相关的业务校验 |

### 1.2 PHP 8 Attribute 注解与路由注册
1. **优先使用原生 Attribute 注解**：
   - 路由与元数据统一在 Controller 上声明 `#[Controller]` 以及 `#[GetMapping]`、`#[PostMapping]` 等；
   - 严禁在注解声明的同时又在 `config/routes.php` 中重复注册同一路由；
   - `config/routes.php` 仅保留极少数无法由注解静态表达的动态路由（须加注释说明）。
2. **依赖注入规范**：
   - 默认强制使用**构造函数类型声明注入**（Constructor Injection），提升代码可测试性与静态类型推导；
   - 避免无节制使用 `#[Inject]` 属性注入。
3. **普通业务类禁止滥用注解**：
   - 不需要由 DI 容器生命周期管理的普通实体（Domain Entity、Value Object、DTO、配置常数），严禁挂载无意义的框架扫描注解。

### 1.3 HTTP 路由与参数约定
- **禁止使用 URL Path 参数承载业务字段**：
  - 严禁设计形如 `/devices/{id}`、`/users/{user_id}/status` 的动态路径路由；
- **读请求（GET）规范**：
  - 标识与查询筛选条件统一使用 **Query 参数**（如 `/devices/detail?id=1`、`/users/list?status=active`）；
- **写请求（POST / PUT / PATCH）规范**：
  - 业务字段与更新数据统一置于 **请求 Body (JSON)** 中；
  - 路由采用稳定动作或资源入口（如 `/devices/rename`，`device_id` 与 `new_name` 均由 Body 传递）；
- **DTO 强制防御性校验**：
  - DTO 必须对 Query 或 Body 中的参数进行严格类型约束、必填项与取值范围校验。

---

# 2. Swoole 协程常驻内存安全黄金红线 (Coroutine & State Safety)

Hyperf 运行在 Swoole 常驻内存模式下，传统的 PHP-FPM “请求结束自动销毁所有变量” 的心智模型在此完全失效。必须严防**跨协程状态串染**：

### 🚨 红线一：严禁在单例属性中存储请求级状态
- Controller、Service、Repository 在 Hyperf 容器中默认均为**长生命周期的共享单例**；
- **绝对禁止**将用户 ID、请求参数、租户信息或私有数据存储在类的普通成员属性（`$this->userId`）或静态属性中；
- 必须强制使用 `Hyperf\Context\Context` 进行协程上下文隔离：
  ```php
  use Hyperf\Context\Context;

  // ❌ 致命错误：在单例类属性中保存用户状态，高并发下导致 A 用户的账单被 B 用户看到
  class OrderService {
      private int $currentUserId; // 绝对禁止！
  }

  // ✅ 唯一正解：使用协程上下文 (协程销毁时自动隔离并清理)
  class OrderService {
      public function setCurrentUser(int $userId): void {
          Context::set('current_user_id', $userId);
      }

      public function getCurrentUser(): ?int {
          return Context::get('current_user_id');
      }
  }
  ```

### 🚨 红线二：禁止使用传统 PHP 全局超全局变量
- **严禁使用** `$_GET`、`$_POST`、`$_REQUEST`、`$_SESSION`、`$GLOBALS`；
- 所有输入必须通过 Hyperf 注入的 `Hyperf\HttpServer\Contract\RequestInterface` 或 DTO 对象安全获取。

### 🚨 红线三：协程并发与异常防击垮 (Worker Safety)
- 在通过 `Coroutine::create` 派生子协程时，**子协程代码体内必须 100% 自包含 `try-catch (\Throwable $e)`**；
- 未捕获的子协程异常会直接导致底层 Swoole Worker 进程异常退出、在途所有请求被腰斩重置：
  ```php
  use Hyperf\Coroutine\Coroutine;
  use Hyperf\Contract\StdoutLoggerInterface;

  Coroutine::create(function () use ($logger) {
      try {
          // 异步执行外部通知或日志上报
          $this->notifyExternalGateway();
      } catch (\Throwable $e) {
          // 必须拦截兜底，严禁抛出到协程顶层
          $logger->error(sprintf('子协程执行异常: %s, 堆栈: %s', $e->getMessage(), $e->getTraceAsString()));
      }
  });
  ```

---

# 3. 数据访问与性能规范 (Data Access & Query Optimization)

### 3.1 杜绝循环内查询 (N+1 Query 绝对红线)
- **严禁在 `foreach` / `for` 循环体内执行 SQL 查询或 Redis 单条读取**；
- 必须在循环外部使用 `whereIn` 或 `MGET` 批量拉取数据，并在内存中通过关联键（KeyBy/GroupBy）对齐：
  ```php
  // ❌ 致命性能瓶颈：循环查询导致 100 次数据库往返 (N+1)
  foreach ($orders as $order) {
      $user = $this->userRepo->findById($order->user_id);
  }

  // ✅ 生产级正解：批量获取并在内存中对齐
  $userIds = array_unique(array_column($orders, 'user_id'));
  $users = $this->userRepo->findListByIds($userIds);
  $userMap = [];
  foreach ($users as $user) {
      $userMap[$user->id] = $user;
  }
  ```

### 3.2 安全的数组与对象属性访问
- 在处理可能存在缺失或嵌套层级深的数据时，禁止直接裸写 `$data['a']['b']['c']`（极易引发 `Undefined array key` 警告）；
- 统一使用 Hyperf 官方内置工具助手：
  - **安全读取**：`data_get($target, 'profile.address.city', '默认值')`；
  - **安全设值**：`data_set($target, 'profile.status', 'active')`。

### 3.3 数据库事务与长事务拆分
- **事务边界由 Service 控制**，使用闭包自动提交/回滚：
  ```php
  use Hyperf\DbConnection\Db;

  Db::transaction(function () use ($orderId) {
      $this->orderRepo->updateStatus($orderId, OrderStatus::PAID);
      $this->accountRepo->debitBalance(...);
  });
  ```
- **大事务与数据迁移拆分**：在批量更新或处理海量数据时，严禁在单一事务中执行超过 1000 行的锁定操作，必须使用 `chunkById` 游标分批次独立提交，防止长事务锁表引发死锁与连接池耗尽。

### 3.4 Redis 规范
- **禁止全量扫描**：严禁在生产环境执行 `KEYS *`；需要模糊匹配 Key 时必须使用 `SCAN` 游标分批迭代；
- **连接池生命周期**：严格使用 Hyperf 依赖注入容器管理的 Redis 客户端，确保协程连接池复用。

---

# 4. 异步队列与定时任务规范 (Async Queue & Crontab)

### 4.1 异步队列 (AsyncQueue / AMQP) 幂等与重试
1. **至少一次投递与消费端幂等**：
   - 网络抖动或超时重发会导致消息被重复投递，消费者逻辑必须以唯一业务编号（如 `order_no`、`msg_id`）为幂等键，消费前先检查状态或通过 Redis 防重锁拦截；
2. **重试上限与指数退避**：
   - 消息处理失败时，必须配置重试次数上限（如 3 次）与递增延迟时间（如 5s -> 30s -> 60s）；
   - 严禁对由于非法参数、业务规则拒绝等不可恢复的错误进行无限重试；达到上限必须入死信队列或记录告警日志。

### 4.2 定时任务多实例并发防护 (Distributed Crontab Lock)
- 在容器化、多 Pod/多实例集群部署环境下，Hyperf 的 Crontab 默认会在每个节点并发触发；
- **定时任务必须依赖分布式锁防重**：
  ```php
  use Hyperf\Crontab\Annotation\Crontab;
  use Hyperf\Redis\Redis;

  #[Crontab(name: "DailyReconcile", rule: "0 2 * * *", memo: "每日对账任务")]
  public function execute(): void
  {
      $lockKey = "crontab:lock:daily_reconcile:" . date('Ymd');
      // 申请 1 小时有效期的分布式锁 (NX + EX)
      $acquired = $this->redis->set($lockKey, 1, ['NX', 'EX' => 3600]);
      if (!$acquired) {
          return; // 已被其他 Pod 实例抢占执行，安全跳过
      }

      $this->reconcileService->run();
  }
  ```

---

# 5. PHP 8.1+ 地道编码风格与类型安全

1. **强制严格类型**：所有 PHP 新文件头部必须显式声明：
   ```php
   <?php

   declare(strict_types=1);
   ```
2. **杜绝无约束裸数组，拥抱强类型**：
   - 方法参数与返回值必须显式标注强类型，善用 PHP 8.1+ `readonly` 属性、联合类型（`int|string`）与枚举类（`enum OrderStatus: string`）；
   - 严禁把结构复杂的实体以未声明任何键的裸关联数组长距离透传。
3. **异常处理原则**：
   - 严禁空 `catch (\Throwable $e) {}` 吞掉异常；
   - 异常日志必须包含 TraceID 与业务关键参数，便于链路追踪。

---

# 6. Hyperf 规范审查 Checklist

- [ ] **四层分层**：Controller 是否未包含 SQL 读写？Service 是否未混入 HTTP 传输对象？
- [ ] **协程状态安全**：是否有请求级状态保存在了单例类的成员属性中？是否使用了 `Context::get/set`？
- [ ] **子协程防御**：派生的异步子协程是否已用 `try-catch (\Throwable $e)` 全局捕获？
- [ ] **路由传参约定**：接口是否避免了 URL Path 传递业务字段？GET 是否用 Query？写接口是否用 Body？
- [ ] **N+1 查询排查**：循环体内是否不存在任何 SQL 或 Redis 单条调用？
- [ ] **队列幂等防重**：消费者是否针对重复消息具备幂等保障？重试是否有明确上限？
- [ ] **定时任务加锁**：Crontab 是否已添加基于 Redis 的分布式互斥锁防止多节点并发重复执行？

