首页 文章

Laravel Ajax 验证

提问于
浏览
1

我理解如何通过 type-hinting 在控制器方法中的类名来验证请求。但是对于 Ajax 请求根据文件,我应该验证控制器中的数据,因为使用验证器类将重定向而不是发送响应。

我正在看的主要部分是:

如果传入请求是 AJAX 请求,则不会生成重定向。相反,具有 422 状态代码的 HTTP 响应将返回到包含验证错误的 JSON 表示的浏览器。

但是,我的控制器如下:

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

    ...
}

我不能为我的生活得到它与 JSON 回应。文档说明如果失败,它会抛出Illuminate\Contracts\Validation\ValidationException异常,但我无法捕获它。

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

我刚试过“手动写出来”整个$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异常。

3 回答

  • 2

    您的声明文档说最好在控制器中验证 AJAX 请求是完全错误的。

    如果您滚动比你所链接的更进一步 - 您将在 FormValidation 部分下看到这一点

    如果验证失败,将生成重定向响应以将用户发送回其先前的位置。错误也将闪现到会话中,以便可以显示。如果请求是 AJAX 请求,则将向用户返回具有 422 状态代码的 HTTP 响应,包括验证错误的 JSON 表示。

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

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

  • 4

    简单地告诉你在标题中想要 json 也应该解决这个问题。如果请求是 json,Laravel 会检查请求是否为 ajax。

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

    解:

    添加标题

    接受:application/json

  • 2

    好的,所以看起来有两个因素。

    • 它重定向而不是使用 JSON 响应的原因是因为没有在 AJAX 请求上设置 X-Requested-With 字段。这个应用程序的 AJAX 包装器被设置为处理跨域请求,这似乎剥离了 X-Requested-With 字段,这使得最终请求看起来 non-ajax 到服务器 - 因此重定向。

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

    解决方案是删除 ajax 请求上的跨域属性,根据回答这篇文章手动添加 X-Requested-With 标头。这将使应用程序看到它是一个 AJAX 请求。

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

相关问题