1

假设有两个 Laravel API 资源BookAuthor,每个资源都有一些验证store请求的规则。

然后,还有第三个 API 资源,API 使用者可以在其中发布特定内容以及 aBook和 an Author。也就是说,store请求必须接受一个Book对象、一个Author对象和第三个FooBar对象:

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

FooBarRequest验证中,重用andrules()是有意义的,但它不起作用: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方法必须返回一个布尔值(即我们应该为每个属性重新编写所有验证逻辑)。

有没有优雅/官方的方式来做到这一点?

4

2 回答 2

1

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

例如,如果您有:

$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
        );
    }
}
于 2021-12-01T20:39:10.110 回答
0

在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',
                ...
            ]
        );
    }
}

我还没有测试过这个,但它看起来可以工作。

于 2020-01-15T16:21:41.353 回答