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

前端 未结 7 1187
臣服心动
臣服心动 2020-12-18 13:17

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

相关标签:
7条回答
  • 2020-12-18 13:24

    A FormRequest throws an Illuminate\Validation\ValidationException Exception when validation fails which has a redirectTo method, and from there the Exception Handler performs the redirect.

    You can achieve your desired behaviour by running your Form Requests manually in your controller within a try/catch block which captures the errors and combines the error bags before redirecting, or if it's essential that you run them by Laravel injecting them into your controller then you would need to add your own exception handler which captures all of the errors, combines them and then redirects after the final Form Request has ran.

    However, it's worth noting, both of those approaches aren't great: they're cumbersome and are going to cause you more problems than they solve. You should try to adhere to the Laravel way of doing things as best possible if you'd like to write a maintainable application.

    A Form Request exists to validate a form, therefore, each Form should have one Form Request, if you wish to compose a Form Request from different sets of rules then that should be done within the Form Request, e.g:

    1. Define your Form Request for your form php artisan make:request StoreMultipleForm
    2. From the rules method on StoreMultipleForm fetch the rules for each of the other Form Requests and then return them together, e.g:

      /**
       * 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. Use the new composed Form Request in your controller, e.g:

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

    The advantages of this method are that it's self-contained, it adheres to the one form one Form Request expectation, it doesn't require changes to the Form Requests you're combining and if you need to add additional rules unique to this form you can do so without creating another Form Request.

    0 讨论(0)
  • 2020-12-18 13:25

    I know this is a pretty old question, but I got annoyed by not being able to chain form requests together so I made a composer package for this, so you don't have to.

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

    0 讨论(0)
  • 2020-12-18 13:27

    I recently came up against this problem, and solved it like this:

    public function rules()
    {
        $request1 = RequestOne::createFrom($this);
        $request2 = RequestTwo::createFrom($this);
    
        return array_merge(
            $request1->rules(),
            $request2->rules()
        );
    }
    
    0 讨论(0)
  • 2020-12-18 13:29

    If I understand correctly, you have 3 forms, each with their own form requests to deal with their respective validation. You also have another form which combines those 3 forms somewhere else and you don't want to repeat yourself by rewriting those validation rules.

    In which case, I would still suggest going with a single form request, but try to combine the rules of each of those individual requests. For example, you use static methods to define your rules on the 3 individual form requests and have each individual request call its own static method to grab them:

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

    And then have your combined request merge all three sets:

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

    Then you can use the single CombinedRequest in your controller method. Of course, if you don't like the static method approach, in your combined request rules method you could just new up each individual request and call the rules method on each of them and merge the results.

    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
            );
        }
    }
    
    0 讨论(0)
  • 2020-12-18 13:34

    You could concatinate all rules and validate manually:

    $allRules = (new TransportationRequest)->rules() + (new PurchaseRequest)->rules() + (new SaleRequest)->rules();
    Validator::make($request->all(), $allRules)->validate();
    
    0 讨论(0)
  • 2020-12-18 13:37

    Turns out if you resolve the request, validation will kick in.
    One caveat of this is that all the validation objects will not kick in at once but depending on your use case, this might be simpler.

        public function store()
        {
            // request()->replace([ some fields to be validated ]);
            resolve(TransportationRequest::class);
            resolve(PurchaseRequest::class);
            resolve(SaleRequest::class);
            // request is valid
        }
    
    0 讨论(0)
提交回复
热议问题