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

时间:2018-01-21 19:35:09

标签: php laravel validation laravel-5.5 request-validation

问题已经被问到here以前版本的laravel尚未回答。

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

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

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

控制器:

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

我已尝试逐个继承表单请求但无法成功。

编辑:

更具体地说我的问题:

我有purchasetransporataionsale的三个单独表单,使用PurchaseRequestTransportationRequestSaleRequest进行单独评估个别行动。

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

这个

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

谢谢..

8 个答案:

答案 0 :(得分:3)

当验证失败并且redirectTo method时,FormRequest会抛出Illuminate\Validation\ValidationException异常,并从那里Exception Handler performs the redirect

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

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

存在表格请求以验证表格,因此,如果您希望从不同的规则集合中撰写表格请求,那么每个表格应该有一个表格请求,这应该在表格请求中完成,例如:

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

    /**
     * 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;
    }
    
  4. 在控制器中使用新的组合表单请求,例如:

    public function store(StoreMultipleForm $request)
    {
        // Do actions here.
    }
    
  5. 这种方法的优点在于它是自包含的,它遵循一种形式的一种表格请求期望,它不需要更改表格请求你&& #39;重新组合,如果您需要添加此表单独有的其他规则,则可以在不创建其他表单请求的情况下执行此操作。

答案 1 :(得分: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。当然,如果您不喜欢静态方法方法,那么在您的组合请求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
        );
    }
}

答案 2 :(得分:2)

我知道这是一个非常老的问题,但是由于无法将表单请求链接在一起而感到恼火,因此我为此编写了一个作曲家程序包,因此您不必这样做。

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

答案 3 :(得分:1)

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

答案 4 :(得分:1)

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

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

答案 5 :(得分:0)

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

using namespace std;
int aa(int n) //
{
    int i=0;
    for(i=n;i>0;i--)
    {
        i=i*(i-1); //body

    }
    return i; //returning i
}

int main()
{

    cout<<aa(8); //function call

    return 0;
}

答案 6 :(得分:0)

如果解决了请求,结果就会生效。
一个警告是,所有验证对象不会立即启动,但是根据您的使用情况,这可能会更简单。

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

答案 7 :(得分: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;
    }
}

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