square/laravel-hyrule

Laravel 构建验证规则的流畅 API

3.0.0 2023-07-07 04:25 UTC

README

Hyrule 提供了一个面向对象的流畅 API,用于构建 Laravel 验证组件的验证规则。这解锁了使定义一组规则以执行复杂的嵌套数据结构(这在 API 开发中很常见)更简单的模式。

为什么

在 Laravel 中定义验证规则涉及手动构建数组。随着业务逻辑的发展,验证规则变得越来越复杂,这些数组会增长,构建它们也会变得更加复杂。很快,你会发现自己在 操作 数组:根据条件添加或删除规则,重构可重用的段等。随着时间的推移,这种模式可能会感觉非常笨拙。管理验证规则定义并不需要太多就能感觉失控。这个库旨在通过提供更好的 API 来解决这个问题,帮助你在长期内保持高效。

  • 流畅 API 允许您以 ergonomically 定义规则,例如轻松添加条件,不再需要易出错的数组操作。
  • 可组合性:简化了可重复使用的规则构建逻辑,可以在多个嵌套级别上多次使用。不再需要传递并重新构造点表示法的前缀。
  • 严格性意味着惊喜更少:推广数据类型的强制执行,并默认拒绝未知字段。

安装

composer require square/laravel-hyrule:^2.0

对于 PHP 7.4 支持,安装 1.* 版本。请参阅 1.x README

设置

1.) 如果您未启用 package discovery,您将需要手动注册服务提供者

// config/app.php

return [
    // ...
    'providers' => [
       // ...
       Square\Hyrule\HyruleServiceProvider::class,
       // etc.
     ],
];

2.) 发布配置

php artisan vendor:publish --provider="Square\Hyrule\HyruleServiceProvider"

使用服务提供者和默认配置将允许您的应用程序使用 StrictValidator

API 基础

初始化规则构建器并添加第一个字段

// Initialize a new builder: it will help you build up your validation rule-set.
$builder = Hyrule::create();

// Describe your expected input:
// It needs the field name *and* the data-type.
// This creates a *Node* that you can then attach rules to:
$builder->string('first_name')
    ->required() // Attach rules. This one marks the field as required.
    ->max(255); // ...and this one says it cannot be greater than 255 chars in length.

完善其余字段及其规则

$builder
    ->string('first_name')
        ->required()
        ->max(255)
        ->end() // Tell the builder you are done w/ this field...
    ->string('last_name') // ...so you can start a new one!
        ->required()
        ->max(255)
        ->end()
    ->integer('age') // ...This field is an integer.
        ->required()
        ->min(21)
        ->max(60)
        ->end();


$rules = $builder->build();

// $rules:
[
    '' => ['required', 'array:first_name,last_name,age'],
    'first_name' => ['string', 'required', 'max:255'],
    'last_name' => ['string', 'required', 'max:255'],
    'age' => ['integer', 'required', 'min:21', 'max:60'],
]

开始验证!

// Compile into an array Illuminate\Validation\Validator understands.
$rules = $builder->build();

// Use it e.g.
$validator = Validator::make($data, $rules);

// ...or
$request->validate($rules);

// etc.

字段 API

Hyrule 强制您为每个字段定义预期的数据类型。它支持所有类型的范围,从标量类型到非标量类型。

标量类型

添加标量字段就像

$builder->string('product_name');
$builder->integer('quantity');
$builder->float('rating');
$builder->numeric('display_price')
$builder->boolean('on_sale');

非标量类型

无论您的验证规则有多么深奥和复杂,您都可以使用相同的 API 集合

对象

使用 ->object(...) 开始定义嵌套字段,例如

$builder
    // "nutritional_facts" is a required field w/ a bunch of nested fields.
    ->object('nutritional_facts')
        ->required()
        // Describe the fields:
        ->integer('servings_per_container')
            ->required()
            ->min(1)
            ->end()
        ->string('serving_size')
            ->required()
            ->min(1)
            ->max(30)
            ->end()
        // "fat", a nested field, has a bunch of nested fields, too.
        ->object('fat')
            ->integer('saturated_fat_grams')->end()
            ->integer('saturated_fat_percent')
                ->max(100)
                ->end();
            ->end();
未知字段

默认情况下,Hyrule 通过仅允许通过字段 API 明确定义的字段来帮助您构建健壮且安全的应用程序。这专门设计用于帮助您有意识地处理期望的数据。例如,这是您的 API 可以进一步清理用户输入的另一个机制。

如果您期望字段通过,库仍然会要求您指定数据类型。但您不需要指定其他规则

Hyrule::create()
    ->string('name')
      ->end()
    // etc.

如果您想允许未知字段通过,请使用此方法在适当的节点上

Hyrule::create()
  ->allowUnknownProperties() // <- Allows unknown fields at root-level.
  ->object('data')
    ->allowUnknownProperties() // <- It does not carry-over. Add it to everywhere you wish to skip this.
    // etc.

标量值数组

没错:从 ->array() 开始

// Defines an array field named "tags"...
$builder
    ->array('tags')
        // Array length must be between 1-10 elements long:
        ->min(1)
        ->max(10)
        // ...and each element (i.e. a tag) must be a string between 3-100 chars in length.
        ->each('string')
            ->min('3')
            ->max('100');
        // etc.

如这个示例所示,Hyrule 对于数组中的内容也推广了严格性。

对象数组

就像定义其他数组字段一样定义它,并使用完全相同的API来定义嵌套字段

$builder
    // Required "skus" must be between 1-10 items.
    ->array('skus')
        ->required()
        ->min(1)
        ->max(10)
        // Each SKU in the array are objects of their own:
        ->each('object')            
            // Each SKU has these fields:
            ->string('name')
                ->required()
                ->max(255)
                ->end()
            ->integer('quantity')
                ->min(0)
                ->end()
            // etc.

文件上传

从2.3版本开始,Hyrule支持指定文件上传的规则

$builder
    ->file('attachment')
        ->required()
        ->mime('image', 'video', 'text')
        ->end()
    // etc.

请参阅以下详细的指南,了解如何通过文件类型(MIME类型)、尺寸等进行文件上传验证

规则API

首先让我们谈谈使用上述Fields API时会发生什么。当你定义一个字段时,构建器会创建并返回一个节点。然后你可以使用规则API在节点上添加验证规则。

基本示例
// Adding built-in validation rules in Laravel
$builder
    ->string('foobar') // Returns a `StringNode` for the "foobar" field.
    ->required() // Adds the "required" validation rule.
    // Supports rules that accepts parameters like:
    ->min(1) // Adds "min:1"
    ->max(255) // Adds "max:1"
    ->requiredIf('vehicle_type', 'car') // Adds "required_if:vehicle_type,car"

    // Supports rules that access multiple parameters like:
    ->in('A', 'B', 'C') // Adds "in:A,B,C"
    // etc.
自定义规则支持

这个库帮助你构建验证规则定义,并且不会限制你使用Laravel没有提供的自定义规则

$builder
    ->string('foobar')
        // Converts camel-case to snake-case notation:
        ->barBaz('olives', 'on', 'pizza') // Adds "bar_baz:olives,on,pizza"

        // Supports raw rule definitions:
        ->rule('required_without:another_field')

        // ... as well as custom Rule objects:
        ->rule(new MyCustomRule());

关于->end()是什么意思?

一旦你理解了Square\Hyrule\Builder管理一个节点树,并且Fields API返回子节点,你所需要知道的就是->end()返回节点的父节点,并且这是遍历回树的方式

$builder = Hyrule::create() // The root
    ->string('name')
        ->required()
        ->end() // Brings us back to $builder, the root node
        
    // New field on root:
    ->object('characteristics')
        ->required()
        ->string('eye_color')
            ->in(...EyeColors::all())
            ->end() // Back to "characteristics"
        ->numeric('height_cm')
            ->end() // Back to "characteristics"
        ->with(...)
    ->end() // Back to $builder, the root node.
    
    // Another field on root:
    ->array('siblings')
        ->max(10)
        ->each('object') // Starts the "*" ObjectNode
            ->string('name')
            ->end() // Back to the "*" ObjectNode
        ->end() // Back to "siblings"
    ->end() // Back to $builder, the root node.

    // etc.

如果你不喜欢这种方式,你可以使用Fields-With API

高级主题