Laravel Ajax 验证

Laravel Ajax validation

我了解如何通过在控制器方法中对 class 名称进行类型提示来验证请求。但是对于 Ajax 请求 According to the documentation,我应该在控制器中验证数据,因为使用验证器 class 将重定向而不是发送响应。

我正在查看的主要部分是:

If the incoming request was an AJAX request, no redirect will be generated. Instead, an HTTP response with a 422 status code will be returned to the browser containing a JSON representation of the validation errors.

但是我的控制器是这样的:

public function update(App\Permission $permission, Request $request)
{
    $this->validate($request, [
        'permission_description' => 'required|string'
    ]);

    ...
}

我这辈子都做不到用 JSON 来回应。文档指出,如果失败,它会抛出 Illuminate\Contracts\Validation\ValidationException 异常,但我无法捕获它。

每当它失败时,它总是重定向回编辑页面。显然我不想要这个,我想要 json 响应。

我刚刚尝试 "manually writing it out" 整个 $v = Validator::make($request->all(), ...); 确实有效,但如果它不起作用,使用 $this->validate() 方法有什么意义?

$this->validate() 方法是否不适用于 AJAX 并且我每次都必须写很长的方式?难道我做错了什么?!

下面是我试过的:

public function update(App\Permission $permission, UpdatePermissionRequest $request)
{
   /** Redirects rather than returns JSON if the validation fails **/
}

----------------------------------

public function update(App\Permission $permission, Request $request)
{
    $this->validate($request, [
        'permission_description' => 'required|string'
    ]);

    /** AND I've also tried: **/

    try {
        $this->validate($request, ['permission_description' => 'required|string']);
    } catch (\Illuminate\Contracts\Validation\ValidationException $e {
        echo $e; /** Echoing for debug reasons **/
        exit;
    }

    ... 
    /** Still redirects the browser, even if it is an AJAX request **/
}

-----------------------------------------

use Validator;
...
public function update(App\Permission $permission, Request $request)
{
    $v = Validator::make($request->all(), [
        'permission_description' => 'required|string'
    ]);

    if($v->fails())
    {
        return response()->json(['reply' => false]);
    }

    /** Works **/
}

更新 文档不正确。它声明 $this->validate() 方法抛出 Illuminate\Contracts\Validation\ValidationException 但它没有。它抛出一个 Illuminate\Http\Exception\HttpResponseException 异常。

好的,看起来有 2 个影响因素。

  1. 重定向而不是响应 JSON 的原因是 X-Requested-With 字段未在 AJAX 请求中设置。这个应用程序的 AJAX 包装器被设置为处理跨域请求,这似乎去掉了 X-Requested-With 字段,这使得服务器的最终请求看起来 non-ajax - 因此重定向。

  2. 它没有捕捉到 Illuminate\Contracts\Validation\ValidationException 异常的原因是因为没有抛出该异常。如果您打开 Illuminate\Foundation\Validation\ValidatesRequest.php,并搜索函数 throwValidationException(),它实际上会抛出一个 HttpResponseException。我试图捕获 HttpResponseException 并成功捕获 - 我认为文档是错误的。

解决方案是删除 ajax 请求中的跨域属性,按照 answer in this post 手动添加 X-Requested-With header。这将使应用程序看到它是一个 AJAX 请求。

如果你想手动捕获异常,你需要捕获 HttpResponseException,而不是 ValidationException

您关于文档说最好在控制器中验证 AJAX 请求的说法完全不正确。

如果您滚动 bit further down from what you linked - 您会在 FormValidation 部分下看到它

If validation fails, a redirect response will be generated to send the user back to their previous location. The errors will also be flashed to the session so they are available for display. If the request was an AJAX request, a HTTP response with a 422 status code will be returned to the user including a JSON representation of the validation errors.

换句话说 - 没有理由不能在简单的 FormRequest 和简单的代码中做到这一点。它会自动处理它是一个 AJAX 调用和 return 适当的 HTTP 响应这一事实。

我一直在我的 L5 应用程序中这样做 - 它运行完美。

只需在 header 中告诉您想要 json 也应该可以解决此问题。 Laravel 检查请求是否为 ajax 或者是否请求 json。

if ($this->ajax() || $this->wantsJson())
{
    return new JsonResponse($errors, 422);
}

解法:

添加header

接受:application/json