即使提供了自定义消息,验证失败也会返回默认错误消息

问题描述 投票:6回答:4

我没有得到我期望的答复。

这是位置Web服务请求的控制器代码:

<?php
namespace App\Http\Controllers;

use App\Location;
use Illuminate\Http\Request;


class LocationController extends Controller
{


    /**
     * Action method to add a location with the supplied Data
     * 
     * @param \Illuminate\Http\Request $p_oRequest Request
     * 
     * @return JSON
     */
    public function add(Request $p_oRequest)
    {

        try {

            $p_oRequest->validate(
                array(
                    'name' => 'required|alpha_num',
                    'user_id' => 'required|integer',
                ),
                array(
                    'name.required' => 'Name is required',
                    'name.string' => 'Name must be alphanumeric',
                    'user_id.required' => 'Curator User Id is required',
                    'user_id.required' => 'Curator User Id must be an integer',
                )
            );

        } catch (\Exception $ex) {

            $arrResponse = array(
                'result' => 0,
                'reason' => $ex->getMessage(),
                'data' => array(),
                'statusCode' => 404
            );

        } finally {

            return response()->json($arrResponse);

        }

    }

}

请求为http://mydomain/index.php/api/v1/location/add?name=@!^

我期望的响应原因是:{“结果”:0,“原因”:“名称必须是字母数字”,“数据”:[],“ statusCode”:404}

我得到的实际响应是:{“ result”:0,“ reason”:“给定的数据无效。”,“ data”:[],“ statusCode”:404}

请帮助。这使我烦恼。

laravel laravel-5 laravel-validation laravel-5.5
4个回答
7
投票

我终于发现了为什么这行不通。这不是实现代码或Laravel中的错误问题,而是以下两者之一:(i)。编写出色的PHP代码来处理不言而喻的结果,显然我没有这么做; (ii)。 Laravel中关于如何实际使用验证错误响应的文档不足。随便挑。

Laravel的验证会引发Illuminate \ Validation \ ValidationError。信不信由你,这实际上将错误消息默认为“给定的数据无效。”,因此当您捕获\ Exception并检索其$ e-> getMessage()时,此默认错误消息就是您(正确)的错误消息得到。

您需要做的是捕获\ Illuminate \ Validation \ ValidationError-我本来应该做的,,! -然后使用其方法来帮助您从中提取错误消息。

这是我想出的解决方案:

<?php
namespace App\Http\Controllers;

use App\Location;
use Illuminate\Http\Request;


class LocationController extends Controller
{

    /**
     * Action method to add a location with the supplied Data
     * 
     * @param \Illuminate\Http\Request $p_oRequest Request
     * 
     * @return JSON
     */
    public function add(Request $p_oRequest)
    {
        try {

            $arrValid = array(
                'name' => 'required|alpha_num',
                'user_id' => 'required|integer',
            );
            $p_oRequest->validate(
                $arrValid,
                array(
                    'name.required' => 'Name is missing',
                    'name.alpha_num' => 'Name must be alphanumeric',
                    'user_id.required' => 'User Id is missing',
                    'user_id.integer' => 'User Id must be an integer',
                )
            );

        } catch (\Illuminate\Validate\ValidationException $e ) {

            /**
             * Validation failed
             * Tell the end-user why
             */
            $arrError = $e->errors(); // Useful method - thank you Laravel
            /**
             * Compile a string of error-messages
             */
            foreach ($arrValid as $key=>$value ) {
                $arrImplode[] = implode( ', ', $arrError[$key] );
            }
            $message = implode(', ', $arrImplode);
            /**
             * Populate the respose array for the JSON
             */
            $arrResponse = array(
                'result' => 0,
                'reason' => $message,
                'data' => array(),
                'statusCode' => $e->status,
            );

        } catch (\Exception $ex) {

            $arrResponse = array(
                'result' => 0,
                'reason' => $ex->getMessage(),
                'data' => array(),
                'statusCode' => 404
            );

        } finally {

            return response()->json($arrResponse);

        }

    }

}

所以,的确,Laravel提供了正确的答案,并按照锡罐侧面的说明做了,但是我没有正确地应用它。无论如何,为了对我和Laravel-sea的其他丢失PHP航海者的未来提供帮助,我提供了解决方案。

此外,感谢Marcin指出了我的错误代码,即使我已经实现了上述解决方案,也会造成问题。


7
投票

问题可能是Laravel的默认Exception处理程序未准备好将详细的验证信息传递回用户。相反,它向用户隐藏了异常详细信息,这通常是正确的做法,因为这可能对除验证之外的其他异常构成安全风险。

换句话说,如果异常处理程序的render函数(在/app/Exceptions/Handler.php中实现)捕获了您的验证错误,则它们将被解释为常规应用程序异常,并且转给用户的常规错误消息将始终读取“给定数据无效”。] >

确保render方法忽略\Illuminate\Validation\ValidationException的实例,并且您应该获得期望的响应:

public function render($request, Exception $exception) {

    if (! $exception instanceof \Illuminate\Validation\ValidationException)) {

        // ... render code for other Exceptions here

    }

}

使异常处理程序在响应中传递ValidationException详细信息的另一种方法是在render方法中执行类似的操作:

if ($exception instanceof ValidationException && $request->expectsJson()) {
    return response()->json(['message' => 'The given data was invalid.', 'errors' => $exception->validator->getMessageBag()], 422);
}

背景

Laravel在这里基本上是(ab)使用异常。通常,Exception表示代码中的(运行时)问题,但是Laravel使用它们作为一种机制来促进请求验证并向用户提供反馈。这就是为什么在这种情况下,让您的异常处理程序处理异常是不正确的-它不是应用程序异常,而是为用户提供的信息。

OP提供的答案中的代码行之有效,因为他自己捕获了ValidationException,从而防止它被应用程序的Exception Handler捕获。我认为,在任何情况下都不会出现这种情况,因为这是各种担忧的明显混合,并且会导致代码太长且无法读取。像我上面显示的那样,仅忽略ValidationExceptions或在Exception Handler中对它们进行不同处理就可以解决问题。


2
投票

我只看过这个,但是您要做的就是移动验证调用之前


1
投票

您的消息应该是验证规则,所以不要:

© www.soinside.com 2019 - 2024. All rights reserved.