Laravel 5.1在表单请求验证之前修改输入

时间:2016-02-06 21:08:17

标签: php validation laravel-5 laravel-5.1

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

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

当我将$this->start_dt输入字段设置为2016-02-06 12:00:00$this->end_dt设置为2016-02-06 13:00:00时,我仍然会收到验证错误“end_dt必须位于start_dt之后”。这意味着当您在$this->start_dt函数中更新$this->end_dtrules()时,输入请求值不会发生变化。

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是下拉字段。因此,我需要通过组合所有字段来创建日期时间,以便我可以进行比较。

5 个答案:

答案 0 :(得分:15)

从laravel 5.4开始,您可以覆盖prepareForValidation的{​​{1}}方法来修改任何输入。 laravel 5.1应该有类似的东西。

您的请求中的示例

ValidatesWhenResolvedTrait

答案 1 :(得分:5)

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:)

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

答案 3 :(得分:1)

尝试以下步骤:

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' => [
        ...
    ],
];

答案 4 :(得分:0)

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

因此,我在app \ Traits \ ConvertBoolean.php中创建了一个特征,如下所示:

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

    // ...
}