6

The question is already asked here for a previous version of laravel and not yet answered.

I have a html form which is validated using three different Form Request Validations. I am able to do this. But, the problem is, the form validations take place one by one. Not at the same time.

If the first form request throws a validation error the form is returned to the view so rest of the two forms doesn't evaluated, hence a proper validation error can't be displayed to the user.

What I want is : validate the form with the three form validation requests rules at the same time.

Controller:

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

I have tried with inheriting the form requests one by one but could not be succeeded.

Edit :

To be more specific to my question:

I do have three seperate forms for purchase, transporataion and sale which are individually valuated using PurchaseRequest, TransportationRequest and SaleRequest for individual operations.

But there is a special case where a single form handles a purchase, transporataion and a sale. I want to validate the form using combining the three form request rules because I didn't want to write the same validation rules again.

This

Note : The fields in the seperate forms and combined form are same.

Thanks..

4

8 回答 8

13

Illuminate\Validation\ValidationException当验证失败时,FormRequest 会抛出一个异常,它有一个redirectTo方法,然后异常Handler从那里执行重定向

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

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

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

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

    /**
     * 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.
    }
    

这种方法的优点是它是自包含的,它遵循一个表单请求的期望,它不需要更改您正在组合的表单请求,如果您需要添加此表单特有的额外规则,您可以可以在不创建另一个表单请求的情况下这样做。

于 2018-01-21T20:26:33.647 回答
2

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

于 2018-01-21T20:21:05.927 回答
2

如果我理解正确,您有 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在你的控制器方法中使用 single 。当然,如果您不喜欢静态方法方法,在您的组合请求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
        );
    }
}
于 2018-01-21T20:27:27.193 回答
2

事实证明,如果您解决了请求,验证将会启动。
其中一个警告是,所有验证对象都不会立即启动,但根据您的用例,这可能会更简单。

    public function store()
    {
        // request()->replace([ some fields to be validated ]);
        resolve(TransportationRequest::class);
        resolve(PurchaseRequest::class);
        resolve(SaleRequest::class);
        // request is valid
    }
于 2020-09-22T14:38:28.500 回答
1

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

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

于 2020-01-28T17:06:11.530 回答
1

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

$allRules = (new TransportationRequest)->rules() + (new PurchaseRequest)->rules() + (new SaleRequest)->rules();
Validator::make($request->all(), $allRules)->validate();
于 2018-01-21T20:30:04.897 回答
0

我最近遇到了这个问题,并像这样解决了它:

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

    return array_merge(
        $request1->rules(),
        $request2->rules()
    );
}
于 2020-05-07T09:29:00.550 回答
0

您可以一个一个地手动执行 Request 类:

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;
    }
}

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

于 2021-06-21T05:20:17.077 回答