Laravel 6 - 在其他请求验证器中重用现有请求验证器的最佳方法

问题描述 投票:0回答:3

假设有两个 Laravel API 资源

Book
Author
,每个资源都有一些用于验证
store
请求的规则。

然后,还有第三个 API 资源,API 使用者可以在其中发布特定内容以及

Book
Author
。也就是说,
store
请求必须接受一个
Book
对象、一个
Author
对象和第三个
FooBar
对象:

// sample POST body
{
  "book": {...book object...},
  "author": {...author object...},
  "foobar": {...foobar object...}
}

FooBarRequest
验证
rules()
中,重用
BookRequest::rules()
AuthorRequest::rules()
是有意义的,但它不起作用:

<?php

namespace App\Http\Requests;

use Illuminate\Foundation\Http\FormRequest;

class FooBarRequest extends FormRequest
{
    public function rules()
    {
        $bookRules = BookRequest::$validationRules;
        $authorRules = AuthorRequest::$validationRules;

        return [
            'book' => $bookRules,
            'authorRules' => $authorRules,
            'foobar' => 'required|...some rules...'
        ];
    }
}

也许使用 Laravel 的 自定义规则,但它并没有多大帮助,因为

passes
方法必须返回一个布尔值(即我们应该为每个属性重写所有验证逻辑)。

有什么优雅/官方的方法可以做到这一点吗?

php laravel validation laravel-formrequest
3个回答
1
投票

Laracasts 上查看此答案:

如果您想在多个地方使用相同的验证规则,也许可以使用一个特征,然后在多个表单请求中使用它。所以对于书籍规则:

<?php

namespace App\Traits;

trait BookValidationTrait
{
    protected function bookRules ()
    {
        return [
            'book_input_1' => 'your rules here',
            'book_input_2' => 'your rules here',
            ...
        ]
    }
}

然后是作者规则:

<?php

namespace App\Traits;

trait AuthorValidationTrait
{
    protected function authorRules ()
    {
        return [
            'author_input_1' => 'your rules here',
            'author_input_2' => 'your rules here',
            ...
        ]
    }
}

然后在您的图书表格中请求课程:

<?php

namespace App\Http\Requests;

use Illuminate\Foundation\Http\FormRequest;
use App\Traits\BookValidationTrait;

class BookRequest extends FormRequest
{
    use BookValidationTrait;

    public function rules()
    {
        return $this->bookRules();
    }
}

在您的作者表单请求类别中:

<?php

namespace App\Http\Requests;

use Illuminate\Foundation\Http\FormRequest;
use App\Traits\AuthorValidationTrait;

class AuthorRequest extends FormRequest
{
    use AuthorValidationTrait;

    public function rules()
    {
        return $this->authorRules();
    }
}

最后,在您的 FooBar 表单请求类中:

<?php

namespace App\Http\Requests;

use Illuminate\Foundation\Http\FormRequest;
use App\Traits\BookValidationTrait;
use App\Traits\AuthorValidationTrait;

class FooBarRequest extends FormRequest
{
    use BookValidationTrait, AuthorValidationTrait;

    public function rules()
    {
        return array_merge(
            $this->bookRules(),
            $this->authorRules(),
            [
                'foobar_input_1' => 'your rules here',
                'foobar_input_2' => 'your rules here',
                ...
            ]
        );
    }
}

我还没有测试过这个,但看起来可行。


1
投票

book
title
属性将属于 验证嵌套数组输入 规则。

例如,如果您有:

$bookRules = ['title' => 'required', 'body' => 'text'];
$authorRules = ['name' => 'required'];

您希望规则如下:

[
    'book.title' => 'required',
    'book.body' => 'text',
    'author.name' => 'required',
    'foobar' => 'required|...some rules...',
];

假设

BookRequest::$validationRules
AuthorRequest::$validationRules
已经返回您想要的内容,您需要执行以下操作才能到达那里:

<?php

namespace App\Http\Requests;

use Illuminate\Foundation\Http\FormRequest;

class FooBarRequest extends FormRequest
{
    public function rules()
    {
        $bookRules = BookRequest::$validationRules;
        $authorRules = AuthorRequest::$validationRules;

        return array_merge(
            $this->getNestedArrayRules($bookRules, 'book'),
            $this->getNestedArrayRules($authorRules, 'author'),
            ['foobar' => 'required|...some rules...']
        );
    }

    protected function getNestedArrayRules($rules, $key) {
        return array_combine(
            array_map(fn ($attribute) =>  "$key.$attribute", array_keys($rules)), 
            $rules
        );
    }
}

1
投票

就您的情况而言,我看到了解决此问题的一种方法,但我也想演示一个示例,当您需要验证一个实体(例如,一本书)时,该示例可以在更简单的情况下提供帮助:

通过 DI 使用 BookRequest:

class FooBarRequest extends FormRequest
{
    public function rules(BookRequest $request)
    {
        return [
            'foobar' => 'required|...some rules...'
        ];
    }
}

针对您的情况,我建议您使用规则。您可以在 FooBarRequest 中使用它们,也可以在其他 FormRequest 类中重用它们:

class FooBarRequest extends FormRequest
{
    public function rules()
    {
        return [
            'book' => [new BookValidationRule()],
            'authorRules' => [new AuthorValidationRule()],
            'foobar' => 'required|...some rules...'
        ];
    }
}
© www.soinside.com 2019 - 2024. All rights reserved.