friendsofhyperf/validated-dto

Hyperf应用程序的验证数据传输对象。


README

Latest Stable Version Total Downloads License

Hyperf应用程序的验证数据传输对象。从laravel-validated-dto派生而来。

文档

https://wendell-adriel.gitbook.io/laravel-validated-dto

安装

composer require friendsofhyperf/validated-dto

生成DTO

您可以使用gen:dto命令创建DTO

php bin/hyperf.php gen:dto UserDTO

DTO将被创建在app/DTO目录中。

定义验证规则

您可以使用与验证Request数据相同的方式验证数据。

<?php

namespace App\DTO;

class UserDTO extends ValidatedDTO
{
    protected function rules(): array
    {
        return [
            'name'     => ['required', 'string'],
            'email'    => ['required', 'email'],
            'password' => ['required'],
        ];
    }
}

创建DTO实例

您可以通过多种方式创建一个DTO实例。

从数组

$dto = UserDTO::fromArray([
    'name' => 'Deeka Wong',
    'email' => 'deeka@example.com',
    'password' => 'D3Crft!@1b2A'
]);

从JSON字符串

$dto = UserDTO::fromJson('{"name": "Deeka Wong", "email": "deeka@example.com", "password": "D3Crft!@1b2A"}');

从请求对象

public function store(RequestInterface $request): JsonResponse
{
    $dto = UserDTO::fromRequest($request);
}

从模型

$user = new User([
    'name' => 'Deeka Wong',
    'email' => 'deeka@example.com',
    'password' => 'D3Crft!@1b2A'
]);

$dto = UserDTO::fromModel($user);

请注意,模型$hidden属性中的字段将不会用于DTO

从Artisan命令

您有三种方式从Artisan命令创建一个DTO实例。

从命令参数

<?php

use App\DTO\UserDTO;
use Hyperf\Command\Command;

class CreateUserCommand extends Command
{
    protected ?string $signature = 'create:user {name} {email} {password}';

    protected string $description = 'Create a new User';

    /**
     * Execute the console command.
     *
     * @return int
     *
     * @throws ValidationException
     */
    public function handle()
    {
        $dto = UserDTO::fromCommandArguments($this);
    }
}

从命令选项

<?php

use App\DTO\UserDTO;
use Hyperf\Command\Command;

class CreateUserCommand extends Command
{
    protected ?string $signature = 'create:user { --name= : The user name } { --email= : The user email } { --password= : The user password }';

    protected string $description = 'Create a new User';

    /**
     * Execute the console command.
     *
     * @return int
     * @throws ValidationException
     */
    public function handle()
    {
        $dto = UserDTO::fromCommandOptions($this);
    }
}

从命令参数和选项

<?php

use App\DTO\UserDTO;
use Hyperf\Command\Command;

class CreateUserCommand extends Command
{
    protected ?string $signature = 'create:user {name}
                                        { --email= : The user email }
                                        { --password= : The user password }';

    protected string $description = 'Create a new User';

    /**
     * Execute the console command.
     *
     * @return int
     *
     * @throws ValidationException
     */
    public function handle()
    {
        $dto = UserDTO::fromCommand($this);
    }
}

访问DTO数据

在您创建您的DTO实例后,您可以像访问对象属性一样访问任何属性。

$dto = UserDTO::fromArray([
    'name' => 'Deeka Wong',
    'email' => 'deeka@example.com',
    'password' => 'D3Crft!@1b2A'
]);

$dto->name; // 'Deeka Wong'
$dto->email; // 'deeka@example.com'
$dto->password; // 'D3Crft!@1b2A'

如果您传递了不在您的DTOrules方法中列出的属性,则这些数据将被忽略,且不会在您的DTO中可用。

$dto = UserDTO::fromArray([
    'name' => 'Deeka Wong',
    'email' => 'deeka@example.com',
    'password' => 'D3Crft!@1b2A',
    'username' => 'john_doe', 
]);

$dto->username; // THIS WON'T BE AVAILABLE IN YOUR DTO

定义默认值

有时我们可以有可选的属性,并且可以具有默认值。您可以在defaults函数中为您的DTO属性定义默认值。

<?php

namespace App\DTO;

use Hyperf\Stringable\Str;

class UserDTO extends ValidatedDTO
{
    protected function rules(): array
    {
        return [
            'name'     => ['required', 'string'],
            'email'    => ['required', 'email'],
            'username' => ['sometimes', 'string'],
            'password' => ['required'],
        ];
    }

    protected function defaults(): array
    {
        return [
            'username' => Str::snake($this->name),
        ];
    }
}

使用上述DTO定义,您可以运行

$dto = UserDTO::fromArray([
    'name' => 'Deeka Wong',
    'email' => 'deeka@example.com',
    'password' => 'D3Crft!@1b2A'
]);

$dto->username; // 'deeka_wong'

转换DTO数据

您可以转换您的DTO到某些格式。

转换为数组

$dto = UserDTO::fromArray([
    'name' => 'Deeka Wong',
    'email' => 'deeka@example.com',
    'password' => 'D3Crft!@1b2A',
]);

$dto->toArray();
// [
//     "name" => "Deeka Wong",
//     "email" => "deeka@example.com",
//     "password" => "D3Crft!@1b2A",
// ]

转换为JSON字符串

$dto = UserDTO::fromArray([
    'name' => 'Deeka Wong',
    'email' => 'deeka@example.com',
    'password' => 'D3Crft!@1b2A',
]);

$dto->toJson();
// '{"name":"Deeka Wong","email":"deeka@example.com","password":"D3Crft!@1b2A"}'

$dto->toJson(true); // YOU CAN CALL IT LIKE THIS TO PRETTY PRINT YOUR JSON
// {
//     "name": "Deeka Wong",
//     "email": "deeka@example.com",
//     "password": "D3Crft!@1b2A"
// }

转换为Eloquent模型

$dto = UserDTO::fromArray([
    'name' => 'Deeka Wong',
    'email' => 'deeka@example.com',
    'password' => 'D3Crft!@1b2A',
]);

$dto->toModel(\App\Model\User::class);
// App\Model\User {#3776
//     name: "Deeka Wong",
//     email: "deeka@example.com",
//     password: "D3Crft!@1b2A",
// }

自定义错误消息、属性和异常

您可以通过在您的DTO类中实现messagesattributes方法来自定义消息和属性。

/**
 * Defines the custom messages for validator errors.
 */
protected function messages() {
    return [];
}

/**
 * Defines the custom attributes for validator errors.
 */
protected function attributes() {
    return [];
}

类型转换

您可以通过在您的DTO中定义一个casts方法来轻松转换您的DTO属性。

/**
 * Defines the type casting for the properties of the DTO.
 *
 * @return array
 */
protected function casts(): array
{
    return [
        'name' => new StringCast(),
        'age'  => new IntegerCast(),
        'created_at' => new CarbonImmutableCast(),
    ];
}

可用类型

数组

对于JSON字符串,它将转换为数组,对于其他类型,它将将它们包裹在数组中。

protected function casts(): array
{
    return [
        'property' => new ArrayCast(),
    ];
}

布尔值

对于字符串值,它使用带有FILTER_VALIDATE_BOOLEAN标志的filter_var函数。

protected function casts(): array
{
    return [
        'property' => new BooleanCast(),
    ];
}

Carbon

这接受任何由Carbon构造函数接受的值。如果找到无效的值,它将抛出\FriendsOfHyperf\ValidatedDTO\Exception\CastException异常。

protected function casts(): array
{
    return [
        'property' => new CarbonCast(),
    ];
}

您还可以在定义转换时传递时区,以便在转换值时使用。

protected function casts(): array
{
    return [
        'property' => new CarbonCast('Europe/Lisbon'),
    ];
}

您还可以在定义转换时传递格式,以便在转换值时使用。如果属性具有与指定格式不同的格式,它将抛出\FriendsOfHyperf\ValidatedDTO\Exception\CastException异常。

protected function casts(): array
{
    return [
        'property' => new CarbonCast('Europe/Lisbon', 'Y-m-d'),
    ];
}

CarbonImmutable

这接受任何由CarbonImmutable构造函数接受的值。如果找到无效的值,它将抛出\FriendsOfHyperf\ValidatedDTO\Exception\CastException异常。

protected function casts(): array
{
    return [
        'property' => new CarbonImmutableCast(),
    ];
}

您还可以在定义转换时传递时区,以便在转换值时使用。

protected function casts(): array
{
    return [
        'property' => new CarbonImmutableCast('Europe/Lisbon'),
    ];
}

您还可以在定义转换时传递格式,以便在转换值时使用。如果属性具有与指定格式不同的格式,它将抛出\FriendsOfHyperf\ValidatedDTO\Exception\CastException异常。

protected function casts(): array
{
    return [
        'property' => new CarbonImmutableCast('Europe/Lisbon', 'Y-m-d'),
    ];
}

集合

对于JSON字符串,它首先将转换为数组,然后再将其包装到Collection对象中。

protected function casts(): array
{
    return [
        'property' => new CollectionCast(),
    ];
}

如果您想将 Collection 中所有的元素进行类型转换,可以将一个 Castable 对象传递给 CollectionCast 构造函数。假设您想要将 Collection 中的所有项目转换为整数

protected function casts(): array
{
    return [
        'property' => new CollectionCast(new IntegerCast()),
    ];
}

这适用于所有 Castable 类型,包括用于嵌套数据的 DTOCastModelCast

DTO

这适用于数组和 JSON 字符串。这将验证数据并为指定的 DTO 进行类型转换。

如果数据对于 DTO 不可用,将抛出 Hyperf\Validation\ValidationException 异常。

如果属性不是一个有效的数组或有效的 JSON 字符串,将抛出 FriendsOfHyperf\ValidatedDTO\Exception\CastException 异常。

如果传递给 DTOCast 构造函数的类不是 ValidatedDTO 实例,将抛出 FriendsOfHyperf\ValidatedDTO\Exception\CastTargetException 异常。

protected function casts(): array
{
    return [
        'property' => new DTOCast(UserDTO::class),
    ];
}

浮点数

如果找到非数值,将抛出 FriendsOfHyperf\ValidatedDTO\Exception\CastException 异常。

protected function casts(): array
{
    return [
        'property' => new FloatCast(),
    ];
}

整数

如果找到非数值,将抛出 FriendsOfHyperf\ValidatedDTO\Exception\CastException 异常。

protected function casts(): array
{
    return [
        'property' => new IntegerCast(),
    ];
}

模型

这适用于数组和 JSON 字符串。

如果属性不是一个有效的数组或有效的 JSON 字符串,将抛出 FriendsOfHyperf\ValidatedDTO\Exception\CastException 异常。

如果传递给 ModelCast 构造函数的类不是 Model 实例,将抛出 FriendsOfHyperf\ValidatedDTO\Exception\CastTargetException 异常。

protected function casts(): array
{
    return [
        'property' => new ModelCast(User::class),
    ];
}

对象

这适用于数组和 JSON 字符串。

如果属性不是一个有效的数组或有效的 JSON 字符串,将抛出 FriendsOfHyperf\ValidatedDTO\Exception\CastException 异常。

protected function casts(): array
{
    return [
        'property' => new ObjectCast(),
    ];
}

字符串

如果数据无法转换为字符串,将抛出 FriendsOfHyperf\ValidatedDTO\Exception\CastException 异常。

protected function casts(): array
{
    return [
        'property' => new StringCast(),
    ];
}

创建自定义类型转换

您可以通过实现 FriendsOfHyperf\ValidatedDTO\Casting\Castable 接口轻松为您的项目创建新的 Castable 类型。此接口有一个必须实现的方法

/**
 * Casts the given value.
 *
 * @param  string  $property
 * @param  mixed  $value
 * @return mixed
 */
public function cast(string $property, mixed $value): mixed;

假设您项目中有一个 URLWrapper 类,并且您希望当将 URL 传递到您的 DTO 中时,它始终返回一个 URLWrapper 实例而不是简单的字符串

class URLCast implements Castable
{
    /**
     * @param  string  $property
     * @param  mixed  $value
     * @return URLWrapper
     */
    public function cast(string $property, mixed $value): URLWrapper
    {
        return new URLWrapper($value);
    }
}

然后您可以将此应用于您的 DTO

class CustomDTO extends ValidatedDTO
{
    protected function rules(): array
    {
        return [
            'url' => ['required', 'url'],
        ];
    }

    protected function defaults(): array
    {
        return [];
    }

    protected function casts(): array
    {
        return [
            'url' => new URLCast(),
        ];
    }
}

联系方式

许可证

MIT