2015-06-16 75 views
0

我想问我应该如何在L5中使用FormRequest处理多个场景的验证?我知道,我被告知我可以创建分离的FormRequest文件来处理不同的验证,但它非常冗余,并且还指出,我需要使用use FormRequest;关键字手动将其注入到控制器中。以前在L4.2中,我可以在我的customValidator.php中定义一个新函数,然后在通过trycatch进行控制器验证期间调用该函数,然后使用以下实现通过服务验证数据。Laravel 5多种场景的FormRequest验证器

class somethingFormValidator extends \Core\Validators\LaravelValidator 
{ 
    protected $rules = array(
     'title'    => 'required', 
     'fullname'   => 'required', 
     // and many more 
     ); 


    public function scenario($scene) 
    { 
     switch ($scene) { 
      case 'update': 
       $this->rules = array(
         'title'    => 'required', 
         'fullname'   => 'required', 
         // and other update validated inputs 
        break; 
     } 

     return $this; 
    } 
} 

,然后在我的LaravelValidator.php

<?php namespace Core\Validators; 

use Validator; 

abstract class LaravelValidator { 

     /** 
     * Validator 
     * 
     * @var \Illuminate\Validation\Factory 
     */ 
     protected $validator; 

     /** 
     * Validation data key => value array 
     * 
     * @var Array 
     */ 
     protected $data = array(); 

     /** 
     * Validation errors 
     * 
     * @var Array 
     */ 
     protected $errors = array(); 

     /** 
     * Validation rules 
     * 
     * @var Array 
     */ 
     protected $rules = array(); 

     /** 
     * Custom validation messages 
     * 
     * @var Array 
     */ 
     protected $messages = array(); 

     public function __construct(Validator $validator) 
     { 
       $this->validator = $validator; 
     } 

     /** 
     * Set data to validate 
     * 
     * @return \Services\Validations\AbstractLaravelValidator 
     */ 
     public function with(array $data) 
     { 
       $this->data = $data; 

       return $this; 
     } 

     /** 
     * Validation passes or fails 
     * 
     * @return Boolean 
     */ 
     public function passes() 
     { 
       $validator = Validator::make(
         $this->data, 
         $this->rules, 
         $this->messages 
       ); 

       if ($validator->fails()) 
       { 
         $this->errors = $validator->messages(); 

         return false; 
       } 

       return true; 
     } 

     /** 
     * Return errors, if any 
     * 
     * @return array 
     */ 
     public function errors() 
     { 
       return $this->errors; 
     } 

} 

,最后这就是我所说的场景内的服务,如本

public function __construct(somethingFormValidator $v) 
    { 
     $this->v = $v; 
    } 

public function updateSomething($array) 
    { 
     if($this->v->scenario('update')->with($array)->passes()) 
      { 
      //do something 
      else 
      { 
      throw new ValidationFailedException(
        'Validation Fail', 
        null, 
        $this->v->errors() 
        ); 
      } 
    } 

所以,现在的问题是,因为我有迁移到L5和L5使用FormRequest,我应该如何在我的代码中使用场景验证?

<?php namespace App\Http\Requests; 

use App\Http\Requests\Request; 

class ResetpasswordRequest extends Request { 

    /** 
    * Determine if the user is authorized to make this request. 
    * 
    * @return bool 
    */ 
    public function authorize() 
    { 
     return true; 
    } 

    /** 
    * Get the validation rules that apply to the request. 
    * 
    * @return array 
    */ 
    public function rules() 
    { 
     return [ 
     'login_email'   => 'required', 
     'g-recaptcha-response' => 'required|captcha', 
     ]; 
    } 


    public function messages() 
    { 
     return [ 
      'login_email.required'    => 'Email cannot be blank', 
      'g-recaptcha-response.required'  => 'Are you a robot?', 
      'g-recaptcha-response.captcha'  => 'Captcha session timeout' 
     ]; 
    } 

    public function scenario($scene) 
    { 
     switch ($scene) { 
      case 'scene1': 
       $this->rules = array(
         //scenario rules 
         ); 
        break; 
     } 

     return $this; 
    } 

} 

也应该如何在控制器中调用它?

public function postReset(ResetpasswordRequest $request) 
    { 
     $profile = ProfileService::getProfileByEmail(Request::input('login_email')); 

     if($profile == null) 
     { 
      $e = array('login_email' => 'This email address is not registered'); 
      return redirect()->route('reset')->withInput()->withErrors($e); 
     } 
     else 
     { 
      //$hash = ProfileService::createResetHash($profile->profile_id); 
      $time = strtotime('now'); 
      $ip = Determinator::getClientIP(); 
      MailProcessor::sendResetEmail(array('email' => $profile->email, 
          'ip' => $ip, 'time' => $time,)); 
     } 
    } 
+0

很长的代码阅读足够..如果你写这个代码,你应该能够知道如何处理它简单的'如果''else' –

+0

是否有一个原因,你不能只是'someFormValidaton'注入你的控制器(或方法)并使用它而不是像以前那样的自定义表单请求对象? – user3158900

回答

1

我相信在手的真正的问题是一切都通过形式请求对象验证它达到你的控制器,你无法设置适当的验证规则之前。

我可以提出的最佳解决方案是在请求对象的构造函数中设置验证规则。不幸的是,我不确定如何或在哪里可以拿出$scene var,因为它似乎在您的示例中被硬编码为'update'

我确实想出了这个。希望在构造函数中阅读我的意见将会有所帮助。

namespace App\Http\Requests; 

use App\Http\Requests\Request; 

class TestFormRequest extends Request 
{ 

    protected $rules = [ 
     'title'    => 'required', 
     'fullname'   => 'required', 
     // and many more 
    ]; 

    public function __construct() 
    { 
     call_user_func_array(array($this, 'parent::__construct'), func_get_args()); 

     // Not sure how to come up with the scenario. It would be easiest to add/set a hidden form field 
     // and set it to 'scene1' etc... 
     $this->scenario($this->get('scenario')); 

     // Could also inspect the route to set the correct scenario if that would be helpful? 
     // $this->route()->getUri(); 
    } 

    /** 
    * Determine if the user is authorized to make this request. 
    * 
    * @return bool 
    */ 
    public function authorize() 
    { 
     return true; 
    } 

    /** 
    * Get the validation rules that apply to the request. 
    * 
    * @return array 
    */ 
    public function rules() 
    { 
     return $this->rules; 
    } 

    public function scenario($scene) 
    { 
     switch ($scene) { 
      case 'scene1': 
       $this->rules = [ 
        //scenario rules 
       ]; 
       break; 
     } 
    } 
} 
0

您可以使用laratalks/validator包进行laravel中多个场景的验证。 see this repo