【问题标题】:Failed validation returns default error message even though custom messages supplied即使提供了自定义消息,验证失败也会返回默认错误消息
【发布时间】:2018-02-25 16:28:02
【问题描述】:

我没有得到预期的响应。

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

<?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=@!^

我期望的响应原因是:{ "result": 0, "reason": "Name must be alphanumeric", "data": [], "statusCode": 404 }

我得到的实际响应是: { "result": 0, "reason": "The given data was invalid.", "data": [], "statusCode": 404 }

请帮忙。这让我很烦。

【问题讨论】:

    标签: laravel laravel-5 laravel-validation laravel-5.5


    【解决方案1】:

    我终于发现了为什么这不起作用。这不是实现代码或 Laravel 中的错误问题,而是以下之一:(i)。编写好的 PHP 代码来处理不言自明的结果,显然我没有这样做; (二)。 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\Validation\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 指出我的错误编码,即使我实施了上述解决方案也会导致问题。

    【讨论】:

    • 这太乱了! laravel 应该提供更简单的方法来做到这一点。感谢这个问题和分析器,并考虑检查它是否正确
    • 感谢stackoverflow.com/users/8745014/gileneusz的支持。我觉得检查自己的答案很尴尬。
    • 检查自己的答案只是向用户展示适合你的方法
    • 这个解决方案帮助我在通过测试时找到错误,谢谢。
    • @steven7mwesigwa 嗨,史蒂文。上面的代码使用的是 Laravel 5.4,所以我需要检查 ValidationException 类的命名空间,你是对的。感谢您指出了这一点。上面的答案已根据您的更正进行了修改。
    【解决方案2】:

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

    换句话说;如果异常处理程序的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) 在这里使用异常。通常,异常表示代码中的(运行时)问题,但 Laravel 使用它们作为促进请求验证并向用户提供反馈的机制。这就是为什么在这种情况下,让您的异常处理程序处理异常是不正确的——它不是应用程序异常,而是针对用户的信息。

    OP 提供的答案中的代码有效,因为他自己捕获了 ValidationException,防止它被应用程序的异常处理程序捕获。我认为在任何情况下都不需要这样做,因为它显然是关注点的混合,并且会产生可怕的冗长和不可读的代码。像我上面展示的那样简单地忽略 ValidationExceptions 或在异常处理程序中对它们进行不同的处理就可以了。

    【讨论】:

      【解决方案3】:

      我刚刚看到这个,但您需要做的就是将验证调用 try/catch 之前移动

      $p_oRequest->validate(
          [
              'name'    => 'required|alpha_num',
              'user_id' => 'required|integer',
          ],
          [
              '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',
          ]
      );
      
      try {
      
      ...
      
      } catch(\Exception $e) {
          return back()->withErrors($e->getMessage())->withInput();
      }
      

      因为 Laravel 会自动捕获验证异常并返回旧输入和一系列错误,您可以像这样输出这些错误

      @if ($errors->any())
          <div class="alert alert-danger">
              <ul>
                  @foreach ($errors->all() as $error)
                      <li>{{ $error }}</li>
                  @endforeach
              </ul>
          </div>
      @endif
      

      【讨论】:

        【解决方案4】:

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

        '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',
        

        你应该有:

        'name.required' => 'Name is required',
        'name.alpha_num' => 'Name must be alphanumeric',
        'user_id.required' => 'Curator User Id is required',
        'user_id.integer' => 'Curator User Id must be an integer',
        

        【讨论】:

        • 那仍然没有解决问题。显然,这是其他 Laravel 开发人员遇到的问题。看github.com/laravel/framework/issues/21059
        • 不,您设置了无效消息。当您使用alpha_num 验证规则时,您应该使用name.alpha_num 使其工作。所以要么你做错了什么,要么你在你的问题中输入了错误的代码
        • 感谢您的回复,Marcin。我做了你推荐的更正。所有的功劳都归功于你,你是对的 - 我犯了错误,他们会产生自己的问题,但是,我的 JSON 中无用响应的根本原因仍然没有得到解决。我发现了更广泛的解决方案,但是我将其作为答案发布。
        【解决方案5】:

        将响应放入变量中并使用 dd() 打印它。您将在“消息”方法中找到它。为我工作。

        dd($response);

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2019-05-21
          • 1970-01-01
          • 2012-07-28
          • 2018-11-17
          • 2020-04-10
          • 2023-03-28
          相关资源
          最近更新 更多