Laravel:表单验证未按预期工作

4
当我尝试使用表单验证来验证来自客户端的数据时,由于rules()中包含的验证规则被违反,因此无法正确验证。即使如此,authorize()方法仍然会被执行。

以下是代码:

class PostAssignRequest extends Request {

    /**
     * Determine if the user is authorized to make this request.
     *
     * @return bool
     */
    public function authorize()
    {
        $params = $this->request->all();

        if(User::find($params['userId'])->company != Auth::user()->company)
        {
            return false;
        }

        return true;
    }

    /**
     * Get the validation rules that apply to the request.
     *
     * @return array
     */
    public function rules()
    {
        $rules = [
            'userId' => 'required|exists:users,id',
            'taskId' => 'required|exists:tasks,id'
        ];

        return $rules;
    }
}

在这个例子中,即使未设置userId参数,也会执行User::find()
我还注意到,如果authorize()方法只返回true,那么我会收到一个422响应,告诉我缺少userId参数。
我该怎么处理呢?我想先检查规则,然后再根据规则进行授权。
3个回答

4
授权和验证在ValidatesWhenResolvedTrait@validate中调用:
public function validate()
{
    $instance = $this->getValidatorInstance();

    if ( ! $this->passesAuthorization())
    {
        $this->failedAuthorization();
    }
    elseif ( ! $instance->passes())
    {
        $this->failedValidation($instance);
    }
}

您可以通过在表单请求中覆盖 validate 方法来更改顺序。如果您希望将其应用于所有请求,请在基类 App\Http\Requests\Request 中进行修改:

public function validate()
{
    $instance = $this->getValidatorInstance();

    if ( ! $instance->passes())
    {
        $this->failedValidation($instance);
    }
    elseif ( ! $this->passesAuthorization())
    {
        $this->failedAuthorization();
    }
}

我喜欢这种方法,看起来是最干净的方式。我找到了ValidatesWhenResolvedTrait,但我没有注意到它被FormRequest使用,所以我没有想到覆盖它。很好的发现 :-) - siannone
不客气。我非常确定这是最干净的方式... ;) - lukasgeiter

1
作为 Laravel 首先执行 authorize(),因此您需要在其中进行手动检查。我猜这并不是你使用它的意思。
如果您收到 422 响应,则正在进行 Ajax 请求。您可以使用响应 422 在客户端代码中处理表单验证错误。

是的,但我在想也许先检查数据是否有效,然后再使用正确的数据执行任何逻辑会更有意义。无论如何,感谢您的建议。 - siannone

0
我建议您使用中间件来进行检查,这更符合您的目的。以下代码应该移动到中间件中。
if(User::find($params['userId'])->company != Auth::user()->company)
{
  return false;
}

中间件不适用于表单验证。 - lukasgeiter
我不是指表单验证,我指的是 if(User::find($params['userId'])->company != Auth::user()->company) { return false; } - Kreshnik Hasanaj
我使用中间件来实现更通用的目的。在这种情况下,我选择了表单验证,因为验证规则可以根据每个API路由非常具体(而且我可以轻松地将它们注入到控制器中)。 - siannone
我不是很确定,但我认为在中间件的handle()方法中也可以从Request对象访问FormRequest数据,例如您可以访问规则。 Laravel 5.1将提供中间件参数,这将使编写更好的代码变得更加容易 :) - Kreshnik Hasanaj

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接