lphilippo/laravel-castable-form-request

Laravel/Lumen 包,用于为表单请求添加 Eloquent 类型的转换。

0.3.3 2023-09-13 08:32 UTC

README

Test Suite Status Total Downloads Latest Stable Version License

首先,您现在可以在 Lumen 中使用类似于 Laravel 的表单请求。此外,您还可以通过默认值和(嵌套!)转换扩展您的 FormRequests,以完全控制进入应用程序的数据。需要注意的是,对于嵌套数组,每个属性都需要验证规则,否则属性将不会包含在清洗后的结果中。

在验证之前,将 defaults() 与请求的数据源合并,而 casts() 在验证成功后应用。通过强制执行此顺序,可以使用转换来控制数据提供给应用程序的类型,无论用户数据的验证如何。这对于内部使用 Carbon 日期特别有用。

与 Laravel 中表单请求的标准实现类似,没有区分请求的各个输入源。

安装

composer require lphilippo/laravel-castable-form-request

Lumen 的配置

要在 Lumen 中使用表单请求,您只需要在 bootstrap/app.php 中注册服务提供器。

$app->register(LPhilippo\CastableFormRequest\ServiceProvider::class);

Lumen 中的使用

简单地从 LPhilippo\CastableFormRequest\Http\Requests\LumenFormRequest 扩展您自己的表单请求,并添加所需的规则、转换和默认值。

Laravel 中的使用

由于本包的 FormRequest 不应替代 Laravel 的标准 FormRequest(除非您不需要重定向操作),所有功能仍可以通过稍微多一点的代码实现。

FormRequest 仅扩展基本类并添加了 LPhilippo\CastableFormRequest\Casting\CastsWhenValidatedTrait。这将允许应用 casts(),但为了使用 defaults(),请将以下代码添加到您的类中

    /**
     * Allow default values through filtering before validation.
     *
     * @return array
     */
    public function prepareForValidation()
    {
        return $this->replace(
            array_merge(
                $this->defaults(),
                $this->all()
            )
        );
    }

完整的 FormRequest 示例

以下是一个完整示例,它使用同一实现中的验证、转换和默认值

use LPhilippo\CastableFormRequest\Http\Requests\FormRequest;

class ProductRequest extends FormRequest
{
    /**
     * @inheritdoc
     */
    public function defaults()
    {
        return [
           'id' => 1,
       ];
    }

    /**
     * @inheritdoc
     */
    public function rules()
    {
        return [
           'created_at' => 'required|date_format:Y-m-d',
           'id' => 'required|integer',
       ];
    }
   
    /**
     * @inheritdoc
     */
    public function casts()
    {
        return [
           'created_at' => 'datetime',
           'id' => 'integer',
       ];
    }
}

在您的控制器中,您可以访问验证过的未转换数据

$request->validated();

或者完全清洗后的数据,这为后续的内部处理做好了准备。

$request->sanitised();

请注意,sanitised 不包括未验证的属性。这也适用于嵌套数组,将剥离未验证的属性。

嵌套验证规则

类似于标准验证规则,转换规则也可以嵌套。例如,以下规则是有效的。请注意,转换规则应始终与验证规则(首先应用)一起工作,否则转换的结果可能不可预期。

    /**
     * @inheritdoc
     */
    public function casts()
    {
        return [
            'products' => 'array',
            'products.*' => 'array',
            'products.*.id' => 'int',
            'products.*.category_id' => 'array',
            'products.*.category_id.*' => 'int',
    }

虽然可以通过仅定义点表示法来缩短此处的写法,因为数组规则将隐含存在

    /**
     * @inheritdoc
     */
    public function casts()
    {
        return [
            'products.*.id' => 'int',
            'products.*.category_id.*' => 'int',
    }

嵌套默认值

可以应用相同的嵌套方法来处理默认值。然而,需要指出的是,只有当结果 validated 内容中包含数组时,才会应用嵌套数组默认值。它不会初始化数组本身。

    /**
     * @inheritdoc
     */
    public function casts()
    {
        return [
            'status' => 'pending',
            'products.*.status' => 'available',
            'provider.country.currency' => 'EUR',
    }

添加自定义验证规则

在某些情况下,指定 $rules 变量中的所有验证规则是不够的。例如,如果基于请求路由需要更定制的验证,可以通过添加以下结构来实现

    /**
     * @inheritdoc
     */
    public function withValidator($validator)
    {
        $entityId = $this->route('id');

        if ($entityId === 1) {
            $validator->addRules([
                'key' => 'required|string|in:' . implode(',', self::RESTRICTED_KEYS),
            ]);
        }
    }

重要限制(设计目的)

由于本包的主要目的是验证进入系统的任何输入,验证规则始终优先。不幸的是,当你在数组上指定任何验证规则(按照Laravel的标准行为),在调用Validator::validated时,数组的元素将不再被过滤。

由于这与我们的目的相悖,该功能被禁用,这允许我们定义每个数组元素。缺点是,原始数据中可能存在的空数组将不会出现在sanitised的结果中。

虽然可能实现,但目前并未考虑在内。