PHPackages                             tangwei/dto - PHPackages - PHPackages  [Skip to content](#main-content)[PHPackages](/)[Directory](/)[Categories](/categories)[Trending](/trending)[Leaderboard](/leaderboard)[Changelog](/changelog)[Analyze](/analyze)[Collections](/collections)[Log in](/login)[Sign up](/register)

1. [Directory](/)
2. /
3. [Utility &amp; Helpers](/categories/utility)
4. /
5. tangwei/dto

ActiveLibrary[Utility &amp; Helpers](/categories/utility)

tangwei/dto
===========

php hyperf dto

v3.2.0(2mo ago)18140.5k↓33.5%82MITPHPPHP &gt;=8.2CI passing

Since Jun 29Pushed 3w ago2 watchersCompare

[ Source](https://github.com/tw2066/dto)[ Packagist](https://packagist.org/packages/tangwei/dto)[ RSS](/packages/tangwei-dto/feed)WikiDiscussions master Synced 2w ago

READMEChangelog (10)Dependencies (29)Versions (61)Used By (2)

Hyperf DTO
==========

[](#hyperf-dto)

[![Latest Stable Version](https://camo.githubusercontent.com/2b522ee0636df7f80fe22c5372a1aab64f7c26d901117a1e25991d4c225669ab/68747470733a2f2f696d672e736869656c64732e696f2f7061636b61676973742f762f74616e677765692f64746f)](https://packagist.org/packages/tangwei/dto)[![Total Downloads](https://camo.githubusercontent.com/8e42d378c91b0fb08cced5bfe670d28d150c792db288a8426a67327fbf317c91/68747470733a2f2f696d672e736869656c64732e696f2f7061636b61676973742f64742f74616e677765692f64746f)](https://packagist.org/packages/tangwei/dto)[![License](https://camo.githubusercontent.com/3054d1db09e585ab675f3ce56fe8bd1d8c71326bed86a3a4261c2b7c7840c2fa/68747470733a2f2f696d672e736869656c64732e696f2f7061636b61676973742f6c2f74616e677765692f64746f)](https://github.com/tw2066/dto)[![PHP Version](https://camo.githubusercontent.com/4f0ff8d47b7c73441eb92a1f49af61c2d6521b14113c8fd85fac4416c863e7cc/68747470733a2f2f696d672e736869656c64732e696f2f62616467652f7068702d253345253344382e322d626c7565)](https://www.php.net)

[English](./README_EN.md) | 中文

基于 [Hyperf](https://github.com/hyperf/hyperf) 框架的 DTO（数据传输对象）映射和验证库，使用 PHP 8 Attributes 特性，提供优雅的请求参数绑定和验证方案。

✨ 特性
----

[](#-特性)

- 🚀 **自动映射** — 请求参数自动映射到 PHP DTO 类
- 🎯 **类型安全** — 利用 PHP 8.2+ 的类型系统，提供完整的类型提示
- 🔄 **递归支持** — 支持数组、嵌套对象、递归结构（最大嵌套深度 100）
- ✅ **数据验证** — 集成 Hyperf 验证器，提供约 90 个验证注解
- 📝 **多种参数源** — 支持 Body、Query、FormData、Header 等多种参数来源
- 🎨 **代码优雅** — 基于 PHP 8 Attributes，代码简洁易读
- 🔧 **易于扩展** — 支持自定义验证规则和响应字段名转换
- 📡 **RPC 支持** — 兼容 JSON-RPC（TCP/HTTP）服务的参数验证

📋 环境要求
------

[](#-环境要求)

- PHP &gt;= 8.2
- Hyperf ~3.2
- （可选）hyperf/validation — 数据验证
- （可选）symfony/serializer + symfony/property-access — RPC 对象序列化

📦 安装
----

[](#-安装)

```
composer require tangwei/dto
```

安装后组件通过 `ConfigProvider` 自动注册，无需额外配置。

📖 快速开始
------

[](#-快速开始)

### 基本使用

[](#基本使用)

#### 1. 创建 DTO 类

[](#1-创建-dto-类)

```
namespace App\Request;

use Hyperf\DTO\Annotation\Validation\Required;
use Hyperf\DTO\Annotation\Validation\Integer;
use Hyperf\DTO\Annotation\Validation\Between;

class DemoQuery
{
    public string $name;

    #[Required]
    #[Integer]
    #[Between(1, 100)]
    public int $age;
}
```

#### 2. 在控制器中使用

[](#2-在控制器中使用)

```
namespace App\Controller;

use Hyperf\HttpServer\Annotation\Controller;
use Hyperf\HttpServer\Annotation\GetMapping;
use Hyperf\DTO\Annotation\Contracts\RequestQuery;
use Hyperf\DTO\Annotation\Contracts\Valid;
use App\Request\DemoQuery;

#[Controller(prefix: '/user')]
class UserController
{
    #[GetMapping(path: 'info')]
    public function info(#[RequestQuery] #[Valid] DemoQuery $request): array
    {
        return [
            'name' => $request->name,
            'age' => $request->age,
        ];
    }
}
```

请求 `/user/info?name=tom&age=20` 时，`$request` 会自动填充并验证；验证失败抛出 `Hyperf\Validation\ValidationException`。

📚 注解说明
------

[](#-注解说明)

### 参数来源注解

[](#参数来源注解)

> 命名空间：`Hyperf\DTO\Annotation\Contracts`

#### RequestBody

[](#requestbody)

获取 POST/PUT/PATCH 请求的 Body 参数：

```
use Hyperf\DTO\Annotation\Contracts\RequestBody;

#[PostMapping(path: 'create')]
public function create(#[RequestBody] CreateUserRequest $request)
{
    // $request 会自动填充 Body 中的数据
}
```

#### RequestQuery

[](#requestquery)

获取 URL 查询参数（GET 参数）：

```
use Hyperf\DTO\Annotation\Contracts\RequestQuery;

#[GetMapping(path: 'list')]
public function list(#[RequestQuery] QueryRequest $request)
{
    // $request 会自动填充 Query 参数
}
```

#### RequestFormData

[](#requestformdata)

获取表单请求数据（Content-Type: multipart/form-data）：

```
use Hyperf\DTO\Annotation\Contracts\RequestFormData;

#[PostMapping(path: 'upload')]
public function upload(#[RequestFormData] UploadRequest $formData)
{
    // $formData 会自动填充表单数据
    // 文件上传需要通过 $this->request->file('field_name') 获取
}
```

#### RequestHeader

[](#requestheader)

获取请求头信息（一个方法中最多只能有一个 `RequestHeader` 参数）：

```
use Hyperf\DTO\Annotation\Contracts\RequestHeader;

#[GetMapping(path: 'info')]
public function info(#[RequestHeader] HeaderRequest $headers)
{
    // $headers 会自动填充请求头数据
}
```

#### Valid

[](#valid)

启用验证，必须与参数来源注解一起使用：

```
#[PostMapping(path: 'create')]
public function create(#[RequestBody] #[Valid] CreateUserRequest $request)
{
    // 请求参数会先验证，验证失败会自动抛出异常
}
```

### 组合使用

[](#组合使用)

可以在同一方法中组合使用多种参数来源：

```
#[PutMapping(path: 'update/{id}')]
public function update(
    int $id,
    #[RequestBody] #[Valid] UpdateRequest $body,
    #[RequestQuery] QueryRequest $query,
    #[RequestHeader] HeaderRequest $headers
) {
    // 同时获取 Body、Query 和 Header 参数
}
```

> ⚠️ **注意**：
>
> - 同一参数上 `RequestBody`、`RequestQuery`、`RequestFormData` 互斥，只能标注其一
> - 同一方法中 `RequestBody` 与 `RequestFormData` 不能同时存在于不同参数上
> - 违反以上约束会在服务启动扫描阶段抛出 `Hyperf\DTO\Exception\DtoException`，提前暴露错误

📝 完整示例
------

[](#-完整示例)

### 控制器示例

[](#控制器示例)

```
namespace App\Controller;

use Hyperf\HttpServer\Annotation\Controller;
use Hyperf\HttpServer\Annotation\GetMapping;
use Hyperf\HttpServer\Annotation\PostMapping;
use Hyperf\HttpServer\Annotation\PutMapping;
use Hyperf\DTO\Annotation\Contracts\RequestBody;
use Hyperf\DTO\Annotation\Contracts\RequestQuery;
use Hyperf\DTO\Annotation\Contracts\RequestFormData;
use Hyperf\DTO\Annotation\Contracts\Valid;

#[Controller(prefix: '/demo')]
class DemoController
{
    #[GetMapping(path: 'query')]
    public function query(#[RequestQuery] #[Valid] DemoQuery $request): array
    {
        return [
            'name' => $request->name,
            'age' => $request->age,
        ];
    }

    #[PostMapping(path: 'create')]
    public function create(#[RequestBody] #[Valid] CreateRequest $request): array
    {
        // 处理创建逻辑
        return ['id' => 1, 'message' => 'Created successfully'];
    }

    #[PutMapping(path: 'update')]
    public function update(
        #[RequestBody] #[Valid] UpdateRequest $body,
        #[RequestQuery] QueryParams $query
    ): array {
        // 同时使用 Body 和 Query 参数
        return ['message' => 'Updated successfully'];
    }

    #[PostMapping(path: 'upload')]
    public function upload(#[RequestFormData] UploadRequest $formData): array
    {
        $file = $this->request->file('photo');
        // 处理文件上传
        return ['message' => 'Uploaded successfully'];
    }
}
```

### DTO 类示例

[](#dto-类示例)

#### 简单 DTO

[](#简单-dto)

```
namespace App\Request;

use Hyperf\DTO\Annotation\Validation\Required;
use Hyperf\DTO\Annotation\Validation\Integer;
use Hyperf\DTO\Annotation\Validation\Between;
use Hyperf\DTO\Annotation\Validation\Email;

class CreateRequest
{
    #[Required]
    public string $name;

    #[Required]
    #[Email]
    public string $email;

    #[Required]
    #[Integer]
    #[Between(18, 100)]
    public int $age;
}
```

#### 嵌套对象 DTO

[](#嵌套对象-dto)

嵌套对象会递归映射并递归验证（验证规则取嵌套类自身的注解）：

```
namespace App\Request;

class UserRequest
{
    public string $name;

    public int $age;

    // 嵌套对象
    public Address $address;
}

class Address
{
    public string $province;

    public string $city;

    public string $street;
}
```

#### 数组类型 DTO

[](#数组类型-dto)

```
namespace App\Request;

use Hyperf\DTO\Annotation\ArrayType;

class BatchRequest
{
    /**
     * @var int[]
     */
    public array $ids;

    /**
     * @var User[]
     */
    public array $users;

    // 使用 ArrayType 注解显式指定类型（优先级高于 @var）
    #[ArrayType(User::class)]
    public array $members;

    // 简单类型也可以使用 PhpType 枚举
    #[ArrayType(\Hyperf\DTO\Type\PhpType::INT)]
    public array $scores;
}
```

#### 请求体为 JSON 数组

[](#请求体为-json-数组)

控制器方法形参声明为 `array`，配合 `@param` 注解指定元素类型，可实现 JSON 数组的批量映射与逐项验证：

```
/**
 * @param User[] $users
 */
#[PostMapping(path: 'batch')]
public function batch(#[RequestBody] #[Valid] array $users): array
{
    // $users 为 User[]，每个元素都已验证并映射
}
```

#### 枚举类型

[](#枚举类型)

PHP 8.1+ 的 BackedEnum 可直接作为属性类型，映射时自动按值转换：

```
enum Status: int
{
    case ACTIVE = 1;
    case DISABLED = 0;
}

class UserRequest
{
    public Status $status; // 请求传 1 时自动映射为 Status::ACTIVE
}
```

#### 自定义字段名

[](#自定义字段名)

```
namespace App\Request;

use Hyperf\DTO\Annotation\JSONField;

class ApiRequest
{
    // 将请求中的 user_name 映射到 userName，响应序列化时也输出 user_name
    #[JSONField('user_name')]
    public string $userName;

    #[JSONField('user_age')]
    public int $userAge;
}
```

✅ 数据验证
------

[](#-数据验证)

> 需要先安装 Hyperf 验证器：`composer require hyperf/validation`

### 内置验证注解

[](#内置验证注解)

本库提供 90+ 个验证注解（命名空间 `Hyperf\DTO\Annotation\Validation`），与 Laravel 验证规则一一对应，常用的包括：

分类注解必填`Required`、`RequiredIf`、`RequiredUnless`、`RequiredWith`、`RequiredWithAll`、`RequiredWithout`、`RequiredWithoutAll`、`RequiredArrayKeys`、`Present`、`Filled`类型`Integer`、`Numeric`、`Boolean`、`Str`、`Arr`、`File`、`Image`、`Json`、`Decimal`大小`Between`、`Min`、`Max`、`Size`、`Digits`、`DigitsBetween`、`MinDigits`、`MaxDigits`、`MultipleOf`、`Dimensions`（图片尺寸）格式`Email`、`Url`、`ActiveUrl`、`Ip`、`Ipv4`、`Ipv6`、`Date`、`DateEquals`、`DateFormat`、`Uuid`、`Ulid`、`Regex`、`NotRegex`、`MacAddress`、`HexColor`、`Lowercase`、`Uppercase`、`Ascii`、`Timezone`字符串`Alpha`、`AlphaNum`、`AlphaDash`、`StartsWith`、`EndsWith`、`DoesntStartWith`、`DoesntEndWith`、`Contains`比较`Gt`、`Gte`、`Lt`、`Lte`、`Same`、`Different`、`Confirmed`、`Before`、`After`、`BeforeOrEqual`、`AfterOrEqual`枚举`In`、`NotIn`、`InArray`、`Distinct`文件`Mimes`、`Mimetypes`、`Extensions`数据库`Unique`、`Exists`（支持传入 Model 类名自动解析表名）排除`Exclude`、`ExcludeIf`、`ExcludeUnless`、`ExcludeWith`、`ExcludeWithout`、`Prohibits`、`Missing`、`MissingIf`、`MissingUnless`、`MissingWith`、`MissingWithAll`其他`Nullable`、`Sometimes`、`Bail`、`Accepted`、`AcceptedIf`、`Declined`、`Validation`（自定义规则）### 使用示例

[](#使用示例)

#### 基本验证

[](#基本验证)

```
use Hyperf\DTO\Annotation\Validation\Required;
use Hyperf\DTO\Annotation\Validation\Integer;
use Hyperf\DTO\Annotation\Validation\Between;

class DemoQuery
{
    #[Required]
    public string $name;

    #[Required]
    #[Integer]
    #[Between(1, 100)]
    public int $age;
}
```

在控制器中使用 `#[Valid]` 注解启用验证：

```
#[GetMapping(path: 'query')]
public function query(#[RequestQuery] #[Valid] DemoQuery $request)
{
    // 参数已经验证通过
}
```

#### 自定义错误消息

[](#自定义错误消息)

每个验证注解的最后一个参数为自定义消息：

```
class UserRequest
{
    #[Required('用户名不能为空')]
    public string $name;

    #[Between(18, 100, '年龄必须在 18-100 之间')]
    public int $age;
}
```

#### 使用 Validation 注解

[](#使用-validation-注解)

`Validation` 注解支持 Laravel 风格的验证规则字符串，并可通过 `customKey` 验证数组元素：

```
use Hyperf\DTO\Annotation\Validation\Validation;

class ComplexRequest
{
    // 使用管道符分隔多个规则
    #[Validation('required|string|min:3|max:50')]
    public string $username;

    // 数组元素验证
    #[Validation('integer', customKey: 'ids.*')]
    public array $ids;
}
```

> ⚠️ **注意**：字符串形式的规则按 `|` 拆分、按 `:` 提取参数，因此规则本身包含 `|` 或 `:` 时（如 `regex:/^(a|b)$/`、`date_format:H:i`）会被错误拆分。涉及正则的规则请使用 `Regex` 专用注解或数组形式。

### 自定义验证规则

[](#自定义验证规则)

继承 `BaseValidation` 类即可创建自定义验证规则：

```
namespace App\Validation;

use Attribute;
use Hyperf\DTO\Annotation\Validation\BaseValidation;

#[Attribute(Attribute::TARGET_PROPERTY)]
class Phone extends BaseValidation
{
    protected mixed $rule = 'regex:/^1[3-9]\d{9}$/';

    public function __construct(string $messages = '手机号格式不正确')
    {
        parent::__construct($messages);
    }
}
```

使用自定义验证：

```
use App\Validation\Phone;
use Hyperf\DTO\Annotation\Validation\Required;

class RegisterRequest
{
    #[Required]
    #[Phone]
    public string $mobile;
}
```

⚙️ 配置
-----

[](#️-配置)

组件无需配置即可工作。如需定制，创建 `config/autoload/dto.php`（或 `api_docs.php`）：

```
