【问题标题】:Laravel 5.1 Modify input before form request validationLaravel 5.1 在表单请求验证之前修改输入
【发布时间】:2016-05-16 17:58:12
【问题描述】:

有没有办法在验证发生之前修改表单请求类中的输入字段?

我想修改一些输入日期字段如下,但它似乎不起作用。

当我将$this->start_dt 输入字段设置为2016-02-06 12:00:00 并将$this->end_dt 设置为2016-02-06 13:00:00 时,我仍然收到验证错误“end_dt must be after start_dt”。这意味着当您在 rules() 函数中更新 $this->start_dt$this->end_dt 时,输入请求值不会改变。

public function rules()
{
    if ($this->start_dt){
        $this->start_dt = Carbon::createFromFormat('d M Y H:i:s', $this->start_dt . ' ' . $this->start_hr . ':'. $this->start_min . ':00');
    }

    if ($this->end_dt){
        $this->end_dt = Carbon::createFromFormat('d M Y H:i:s', $this->end_dt . ' ' . $this->end_hr . ':'. $this->end_min . ':00');
    }

    return [
        'start_dt' => 'required|date|after:yesterday',
        'end_dt' => 'required|date|after:start_dt|before:' . Carbon::parse($this->start_dt)->addDays(30)            
    ];
}

注意: start_dtend_dt 是日期选择器字段,start_hrstart_min 是下拉字段。因此,我需要通过组合所有字段来创建日期时间,以便进行比较。

【问题讨论】:

标签: php validation laravel-5 laravel-5.1


【解决方案1】:

您可以执行以下操作:

public function rules(Request $request)
{
    if ($request->has('start_dt')){
        $request->replace('start_dt', Carbon::createFromFormat('d M Y H:i:s', $request->start_dt . ' ' . $request->start_hr . ':'. $request->start_min . ':00'));
    }

    if ($request->has('end_dt')){
         $request->replace('end_dt' ,Carbon::createFromFormat('d M Y H:i:s', $request->end_dt . ' ' . $request->end_hr . ':'. $request->end_min . ':00'));
    }

    return [
        'start_dt' => 'required|date|after:yesterday',
        'end_dt' => 'required|date|after:start_dt|before:' . Carbon::parse($request->start_dt)->addDays(30)            
    ];
}

【讨论】:

    【解决方案2】:

    从 laravel 5.4 开始,您可以覆盖 ValidatesWhenResolvedTraitprepareForValidation 方法来修改任何输入。 laravel 5.1 应该可以实现类似的功能。

    请求中的示例

    /**
     * Modify the input values
     *
     * @return void
     */
    protected function prepareForValidation() {
    
        // get the input
        $input = array_map('trim', $this->all());
    
        // check newsletter
        if (!isset($input['newsletter'])) {
            $input['newsletter'] = false;
        }
    
        // replace old input with new input
        $this->replace($input);
    }
    

    【讨论】:

    • 这是否记录在任何地方?否则,它可能会像以前的其他解决方案一样在次要版本升级中静默中断。
    【解决方案3】:

    FormRequest 有一个方法 validationData() 返回要验证的数据,所以我在我的表单请求中覆盖它:

    <?php
    
    namespace App\Http\Requests;
    
    use Illuminate\Foundation\Http\FormRequest;
    
    class MyClassRequest extends FormRequest
    {
        ...
        /**
         * Get data to be validated from the request.
         *
         * @return array
         */
        public function validationData() {
            return array_merge(
                $this->all(),
                [
                    'number' => preg_replace("/[^0-9]/", "", $this->number)
                ]
            );
        }
        ...
    }
    

    我使用 Laravel 5.4 运行良好 :)

    【讨论】:

    • 嗨 FabulousCo,你能告诉我你的 FormRequest 和你使用它的控制器方法吗?
    • 嗨,Yassine,Thomas 的例子虽然有效!无论如何谢谢:)
    • 如果你把这行放在 $this->replace($data) 这对我有用 所以: public function validationData() { $data = array_merge( $this->all(), [ 'number ' => preg_replace("/[^0-9]/", "", $this->number) ] ); $this->replace($data); return $data; }
    【解决方案4】:

    试试这些步骤:

    1- 中间件

    首先你应该在app/Http/Middleware中创建一个中间件:

    <?php
    
    namespace App\Http\Middleware;
    
    use Illuminate\Foundation\Http\Middleware\TransformsRequest;
    
    class DateTimeMiddleware extends TransformsRequest
    {
        protected $fields = [
            'birth_date' => 'toGregorian',
            'created_at' => 'toDateTime',
        ];
    
        protected function transform($key, $value)
        {
            if (!array_key_exists($key, $this->fields)) {
                return $value;
            }
    
            $function = $this->fields[$key];
    
            return call_user_func($function, $value);
        }
    }
    

    使用此中间件,您可以在调用验证之前定义要操作它们的字段,并调用特定函数来操作它们。

    注意:我在自己的辅助函数中定义了toGregoriantoDateTime。你可以用你自己的函数来处理它

    2- 内核

    然后像下面这样修改Http/Kernel.php

    protected $middlewareGroups = [
        'web' => [
            ...
    
            \App\Http\Middleware\EnglishStrings::class,
        ],
    
        'api' => [
            ...
        ],
    ];
    

    【讨论】:

      【解决方案5】:

      我对此采取了另一种方法,因为我希望能够在我的控制器中使用$model-&gt;fill($validated);。因此,我需要确保复选框已包含在 false 中,否则它们将被排除在数组之外。

      所以,我在 app\Traits\ConvertBoolean.php 中创建了一个 trait,如下:

      <?php
      
      namespace App\Traits;
      
      trait ConvertBoolean
      {
          // protected $boolean_attributes = [];
      
          /**
           * Override the FormRequest prepareForValidation() method to
           * add boolean attributes specified to the request data, setting
           * their value to the presence of the data in the original request.
           *
           * @return void
           */
          protected function prepareForValidation() {
      
              if (isset($this->boolean_attributes) && is_array($this->boolean_attributes)) {
      
                  $attrs_to_add = [];
      
                  foreach ($this->boolean_attributes as $attribute) {
                      $attrs_to_add[$attribute] = $this->has($attribute);
                  }
      
                  $this->merge($attrs_to_add);
              }
          }
      }
      

      该特征在请求中查找数组$this-&gt;boolean_attributes 的存在。如果找到,它会遍历每一个并将属性添加到请求数据中,并将值设置为原始请求数据中属性的存在。

      它忽略了 HTML 表单的复选框值。在大多数情况下,这不是问题,但如果需要,您可以更改特征中的逻辑以查找特定值。

      现在我有了这个特性,然后我可以在任何请求中使用它,如下所示:

      use App\Traits\ConvertBoolean;
      
      class MyUpdateRequest extends FormRequest
      {
          use ConvertBoolean;
      
          protected $boolean_attributes = ['my_checkbox'];
      
          // ... other class code
      
      
          public function rules()
          {
              // Note that the data is added to the request data,
              // so you still need a validation rule for it, in
              // order to receive it in the validated data.
              return [
                  'my_checkbox' => 'boolean',
                  // other rules
              ];
          }
      }
      

      如果您想在请求中使用$this-&gt;prepareForValidation(),这仍然是可能的。

      更改MyRequest,如下:

      use App\Traits\ConvertBoolean;
      
      class MyUpdateRequest extends FormRequest
      {
          use ConvertBoolean {
              prepareForValidation as traitPrepareForValidation;
          }
      
          protected function prepareForValidation() {
      
              // the stuff you want to do in MyRequest
              // ...
      
              $this->traitPrepareForValidation();
          }
      
          // ...
      }
      

      【讨论】:

        猜你喜欢
        • 2015-10-29
        • 2016-01-20
        • 1970-01-01
        • 2016-03-11
        • 1970-01-01
        • 1970-01-01
        • 2017-02-23
        • 2017-07-19
        • 2015-11-07
        相关资源
        最近更新 更多