Laravel 5.5 - 验证多个表单请求 - 同时

Laravel 5.5 - Validate Multiple Form Request - at the same time

here 以前版本的 laravel 已经问过这个问题,但尚未回答。

我有一个 html form,它使用三个不同的 Form Request Validations 进行了验证。我能够做到这一点。但是,问题是,表单验证是一个接一个地进行的。不是同时。

如果第一个表单请求抛出验证错误,表单将返回给 view,因此不会评估其余两个表单,因此无法向用户显示正确的验证错误。

我想要的是:同时用三个表单验证请求rules验证表单

控制器:

public function store(TransportationRequest $request1, PurchaseRequest $request2, SaleRequest $request3)
    {
        //do actions here
    }

我尝试过一个接一个地继承表单请求,但没有成功。

编辑:

更具体地回答我的问题:

我确实有 purchasetransporataionsale 三种不同的形式,它们分别使用 PurchaseRequestTransportationRequestSaleRequest 用于个人操作。

但是有一种特殊情况,其中单个表单处理 purchasetransporataionsale我想结合使用三种表单请求规则来验证表单,因为我不想再次编写相同的验证规则。

这个

注意:单独表格和组合表格中的字段相同。

谢谢..

我会创建包含每个 FormRequest 规则的特征 - 购买、运输和销售。在特定的 FormRequest 中使用该特征,然后当您需要所有规则时,您可以在组合的 FormRequest 中使用所有三个特征,然后合并规则数组。

FormRequest 在验证失败时抛出一个 Illuminate\Validation\ValidationException 异常,其中有一个 redirectTo method, and from there the Exception Handler performs the redirect.

您可以通过 运行 在您的控制器中的 try/catch 块中手动合并您的表单请求来实现您想要的行为,该块捕获错误并在重定向之前合并错误包,或者如果必须你 运行 它们通过 Laravel 将它们注入你的控制器然后你需要添加你自己的异常处理程序来捕获所有错误,组合它们然后在最终表单请求有 运行.

但是,值得注意的是,这两种方法都不是很好:它们很麻烦,并且会给您带来比解决的问题更多的问题。如果您想编写一个可维护的应用程序,您应该尽量遵循 Laravel 的做事方式。

存在用于验证表单的表单请求,因此,每个表单都应该有一个表单请求,如果您希望根据不同的规则集组成一个表单请求,那么应该在表单请求中完成,例如:

  1. 为表单定义表单请求 php artisan make:request StoreMultipleForm
  2. StoreMultipleForm 上的 rules 方法获取每个其他表单请求的 rules,然后 return 将它们放在一起,例如:

    /**
     * Get the validation rules that apply to the request.
     *
     * @return array
     */
    public function rules()
    {
        $formRequests = [
          TransportationRequest::class,
          PurchaseRequest::class,
          SaleRequest::class
        ];
    
        $rules = [];
    
        foreach ($formRequests as $source) {
          $rules = array_merge(
            $rules,
            (new $source)->rules()
          );
        }
    
        return $rules;
    }
    
  3. 在您的控制器中使用新的组合表单请求,例如:

    public function store(StoreMultipleForm $request)
    {
        // Do actions here.
    }
    

这种方法的优点是它是自包含的,它符合一个表单一个表单请求的期望,它不需要更改您的表单请求重新组合,如果您需要添加此表单独有的其他规则,您可以这样做而无需创建 另一个 表单请求。

如果我没理解错的话,你有 3 个表单,每个表单都有自己的表单请求来处理各自的验证。您还有另一种形式,它在其他地方组合了这 3 种形式,并且您不想通过重写这些验证规则来重复自己。

在这种情况下,我仍然建议使用单个表单请求,但尝试结合每个单独请求的规则。例如,您使用静态方法在 3 个单独的表单请求上定义规则,并让每个单独的请求调用自己的静态方法来获取它们:

class TransportationRequest extends FormRequest
{
    public static function getRules()
    {
        return []; // Return rules for this request
    }

    public function rules()
    {
        return static::getRules();
    }
}

class PurchaseRequest extends FormRequest
{
    public static function getRules()
    {
        return []; // Return rules for this request
    }

    public function rules()
    {
        return static::getRules();
    }
}

class SaleRequest extends FormRequest
{
    public static function getRules()
    {
        return []; // Return rules for this request
    }

    public function rules()
    {
        return static::getRules();
    }
}

然后让您的组合请求合并所有三组:

class CombinedRequest extends FormRequest
{
    public function rules()
    {
        return array_merge(
            TransportationRequest::getRules(),
            SaleRequest::getRules(),
            PurchaseRequest::getRules()
        );
    }
}

然后您可以在控制器方法中使用单个 CombinedRequest。当然,如果您不喜欢静态方法方法,在您的组合请求 rules 方法中,您可以 new 启动每个单独的请求并在每个请求上调用 rules 方法,然后合并结果。

class CombinedRequest extends FormRequest
{
    public function rules()
    {
        $transportation = (new TransportationRequest())->rules();
        $sale = (new SaleRequest())->rules();
        $purchase = (new PurchaseRequest())->rules();

        return array_merge(
            $transportation,
            $sales,
            $purchase
        );
    }
}

您可以连接所有规则并手动验证:

$allRules = (new TransportationRequest)->rules() + (new PurchaseRequest)->rules() + (new SaleRequest)->rules();
Validator::make($request->all(), $allRules)->validate();

我知道这是一个很老的问题,但我对无法将表单请求链接在一起感到恼火,所以我为此制作了一个作曲家包,所以你不必这样做。

https://github.com/sharpie89/laravel-multiform-request

我最近遇到了这个问题,是这样解决的:

public function rules()
{
    $request1 = RequestOne::createFrom($this);
    $request2 = RequestTwo::createFrom($this);

    return array_merge(
        $request1->rules(),
        $request2->rules()
    );
}

事实证明,如果您解决请求,验证就会开始。
需要注意的是,所有验证对象不会立即启动,但根据您的用例,这可能更简单。

    public function store()
    {
        // request()->replace([ some fields to be validated ]);
        resolve(TransportationRequest::class);
        resolve(PurchaseRequest::class);
        resolve(SaleRequest::class);
        // request is valid
    }

可以手动执行请求类一一执行:

public function store()
{
    $isValid = true;
    try{
        app(TransportationRequest::class);
    } catch (Illuminate\Validation\ValidationException $ex){
        $isValid = false ;
    }
    try{
        app(PurchaseRequest::class);
    } catch (Illuminate\Validation\ValidationException $ex){
        $isValid = false ;
    }
    try{
        app(SaleRequest::class);
    } catch (Illuminate\Validation\ValidationException $ex){
        $isValid = false ;
    }
    if (!$isValid){
        throw $ex;
    }
}

如果其中一个验证失败,用户将被重定向回上一页并出现错误。