使用 Dingo\API 中的 FormRequest 时,422 错误提示的 message 自定义,以及提示汉化。

使用 FormRequest ,会让 Controller 看起来更为整洁。因为项目需求,我们项目中使用的是 Dingo\Api\Http\FormRequest 。本文主要解决的是,在该种情况下 422 错误提示的汉化以及message 的自定义。
这只是我个人的解决办法,如有好的解决方法可以指出,但不要喷我,会受不了鸟~~

一、问题状况阐述

原始代码如下:

<?php

namespace App\Http\Requests;

use Dingo\Api\Http\FormRequest;

class PostRequest extends FormRequest
{
    public function authorize()
    {
        return true;
    }

    public function rules()
    {
        switch ($this->method()) {
            case 'PUT':
                return [
                    'title' => 'required'
                ];
            case 'POST':
                return [
                    'title' => 'required'
                ];
            default:
                return [];
        }
    }
}

默认错误提示如下:

{
    "message": "422 Unprocessable Entity.",
    "status_code": 422,
    "errors": {
        "title": [
            "The title field is required."
        ]
    }
}

需要优化点:
1、提示为中文提示
2、422错误时,message 默认为errors 中的第一条

期望出现的提示如下:

{
    "message": "必须指定:标题",
    "status_code": 422,
    "errors": {
        "title": [
            "必须指定:标题"
        ]
    }
}

二、解决问题

第一步:首先将项目中的语言汉化(若已汉化,请跳过次步骤)

1、 在 resources/lang 下目录下,建立一个与 en 对应的文件夹 zh
zh文件夹下新建如下四个文件:

auth.php:

<?php

return [

    /*
    |--------------------------------------------------------------------------
    | Authentication Language Lines
    |--------------------------------------------------------------------------
    |
    | The following language lines are used during authentication for various
    | messages that we need to display to the user. You are free to modify
    | these language lines according to your application's requirements.
    |
    */

    'failed' => '当前凭证与我们的记录不相符',
    'throttle' => '登录操作太频繁,请等待 :seconds 秒后重试。',

];

pagination.php:

<?php

return [

    /*
    |--------------------------------------------------------------------------
    | Pagination Language Lines
    |--------------------------------------------------------------------------
    |
    | The following language lines are used by the paginator library to build
    | the simple pagination links. You are free to change them to anything
    | you want to customize your views to better match your application.
    |
    */

    'previous' => '« 上一页',
    'next' => '下一页 »',

];

passwords.php:

<?php

return [

    /*
    |--------------------------------------------------------------------------
    | Password Reset Language Lines
    |--------------------------------------------------------------------------
    |
    | The following language lines are the default lines which match reasons
    | that are given by the password broker for a password update attempt
    | has failed, such as for an invalid token or invalid new password.
    |
    */

    'password' => '密码必须最少为 6 个字符并与确认密码相同。',
    'reset' => '您的密码已重置!',
    'sent' => '我们已将密码重置链接发送到您的邮箱!',
    'token' => '重置密码的令牌无效。',
    'user' => "未找到使用此邮箱的用户。",

];

validation.php:

<?php

return [

    /*
    |--------------------------------------------------------------------------
    | Validation Language Lines
    |--------------------------------------------------------------------------
    |
    | The following language lines contain the default error messages used by
    | the validator class. Some of these rules have multiple versions such
    | as the size rules. Feel free to tweak each of these messages here.
    |
    */

    'accepted' => ':attribute 必须为已接受',
    'active_url' => ':attribute 不是有效的 URL',
    'after' => ':attribute 必须大于 :date',
    'after_or_equal' => ':attribute 必须大于或等于 :date',
    'alpha' => ':attribute 可接受类型:字母',
    'alpha_dash' => ':attribute 可接受类型:字母、数字、短划线和下划线',
    'alpha_num' => ':attribute 可接受类型:字母、数字',
    'array' => ':attribute 可接受类型:数组',
    'before' => ':attribute 必须小于 :date',
    'before_or_equal' => ':attribute 必须小于或等于 :date',
    'between' => [
        'numeric' => ':attribute 必须介于 [:min - :max] 之间',
        'file' => ':attribute 最小::min KB,最大::max KB',
        'string' => ':attribute 最少::min 个字符,最多::max 个字符',
        'array' => ':attribute 最少::min 项,最多::max 项',
    ],
    'boolean' => ':attribute 可接受类型:是 或 否',
    'confirmed' => 'The :attribute confirmation does not match.',
    'date' => ':attribute 不是有效的日期',
    'date_format' => ':attribute 格式错误,格式::format.',
    'different' => ':attribute 不能等于 :other',
    'digits' => ':attribute 必须是 :digits 位数',
    'digits_between' => ':attribute 最少 :min 位数,最多::max 位数',
    'dimensions' => ':attribute 图片尺寸不匹配',
    'distinct' => ':attribute 已存在相同的选项',
    'email' => ':attribute 不是有效的邮箱地址',
    'exists' => '不存在的选项::attribute',
    'file' => ':attribute 必须是一个有效的文件',
    'filled' => ':attribute 必须填写',
    'gt' => [
        'numeric' => ':attribute 必须大于 :value.',
        'file' => ':attribute 必须大于 :value KB',
        'string' => ':attribute 必须大于 :value 个字符',
        'array' => ':attribute 必须大于 :value 项',
    ],
    'gte' => [
        'numeric' => ':attribute 必须大于或等于 :value',
        'file' => ':attribute 必须大于或等于 :value KB',
        'string' => ':attribute 必须大于或等于 :value 个字符',
        'array' => ':attribute 必须大于或等于 :value 项',
    ],
    'image' => ':attribute 必须是一个图像',
    'in' => ':attribute 不是一个有效的值',
    'in_array' => ':other 不包含 :attribute',
    'integer' => ':attribute 必须是整数',
    'ip' => ':attribute 无效的 IP 地址',
    'ipv4' => ':attribute 无效的 IPv4 地址',
    'ipv6' => ':attribute 无效的 IPv6 地址',
    'json' => ':attribute 无效的 JSON 字符串',
    'lt' => [
        'numeric' => ':attribute 必须小于 :value.',
        'file' => ':attribute 必须小于 :value KB',
        'string' => ':attribute 必须小于 :value 个字符',
        'array' => ':attribute 必须小于 :value 项',
    ],
    'lte' => [
        'numeric' => ':attribute 必须小于或等于 :value',
        'file' => ':attribute 必须小于或等于 :value KB',
        'string' => ':attribute 必须小于或等于 :value 个字符',
        'array' => ':attribute 必须小于或等于 :value 项',
    ],
    'max' => [
        'numeric' => ':attribute 不能大于 :max',
        'file' => ':attribute 不能大于 :max KB',
        'string' => ':attribute 不能大于 :max 个字符',
        'array' => ':attribute 不能多于 :max 项',
    ],
    'mimes' => ':attribute 的文件类型必须是: :values.',
    'mimetypes' => ':attribute 的文件类型必须是: :values.',
    'min' => [
        'numeric' => ':attribute 最小值::min.',
        'file' => ':attribute 不能小于 :min KB',
        'string' => ':attribute 最少 :min 个字符',
        'array' => ':attribute 最少包含 :min 项',
    ],
    'not_in' => '当前选项 :attribute 无效',
    'not_regex' => ':attribute 格式错误',
    'numeric' => ':attribute 必须是数值',
    'present' => ':attribute 必须存在',
    'regex' => ':attribute 格式错误',
    'required' => '必须指定::attribute',
    'required_if' => '当 :other 等于 :value 时,必须指定::attribute',
    'required_unless' => '除非 :values 包含 :other,否则必须指定::attribute',
    'required_with' => '当 :values 存在时,必须指定::attribute',
    'required_with_all' => '当 :values 存在时,必须指定::attribute',
    'required_without' => '当 :values 不存在时,必须指定::attribute',
    'required_without_all' => '当 :values 未指定时,必须指定::attribute',
    'same' => ':attribute 必须与 :other 相匹配',
    'size' => [
        'numeric' => ':attribute 必须是 :size',
        'file' => ':attribute 必须是 :size KB',
        'string' => ':attribute 必须是 :size 个字符',
        'array' => ':attribute 必须是 :size 项',
    ],
    'string' => ':attribute 必须是字符串',
    'timezone' => ':attribute 必须是有效的时区',
    'unique' => ':attribute 不能与已存在的项相同',
    'uploaded' => ':attribute 上传失败',
    'url' => ':attribute 格式错误',

    /*
    |--------------------------------------------------------------------------
    | Custom Validation Language Lines
    |--------------------------------------------------------------------------
    |
    | Here you may specify custom validation messages for attributes using the
    | convention "attribute.rule" to name the lines. This makes it quick to
    | specify a specific custom language line for a given attribute rule.
    |
    */

    'custom' => [
        'attribute-name' => [
            'rule-name' => 'custom-message',
        ],
    ],

    /*
    |--------------------------------------------------------------------------
    | Custom Validation Attributes
    |--------------------------------------------------------------------------
    |
    | The following language lines are used to swap attribute place-holders
    | with something more reader friendly such as E-Mail Address instead
    | of "email". This simply helps us make messages a little cleaner.
    |
    */

    'attributes' => [],

];

2 、指定默认语言为中文
修改 config/app.php 文件 中的 locale

 'locale' => 'zh',

第二步:指定 request 文件中对应的属性中文名

修改对应的 request 文件,添加attributes方法。指定对应的属性中文名

<?php

namespace App\Http\Requests;

use Dingo\Api\Http\FormRequest;

class PostRequest extends FormRequest
{
    public function authorize()
    {
        return true;
    }

    public function attributes()
    {
        return [
            'title' => "标题",
        ];
    }

    public function rules()
    {
        switch ($this->method()) {
            case 'PUT':
                return [
                    'title' => 'required'
                ];
            case 'POST':
                return [
                    'title' => 'required'
                ];
            default:
                return [];
        }
    }
}

此时、422 提示信息如下

{
    "message": "422 Unprocessable Entity.",
    "status_code": 422,
    "errors": {
        "title": [
            "必须指定:标题"
        ]
    }
}

第三步:修改 message 提示内容

重写 FormRequest 中的 failedValidation 方法即可

    protected function failedValidation(Validator $validator)
    {
        if ($this->container['request'] instanceof \Illuminate\Http\Request) {
            throw new ResourceException($validator->errors()->first(), $validator->errors());
        }

        throw (new ValidationException($validator))
            ->errorBag($this->errorBag)
            ->redirectTo($this->getRedirectUrl());
    }

由于 failedValidationauthorize 方法在所有的 request 中都一样,SO 我们提出一个基类出来。代码文件如下:
App\Http\Requests 中 Request 基类文件:

<?php
namespace App\Http\Requests;

use Dingo\Api\Exception\ResourceException;
use Illuminate\Contracts\Validation\Validator;
use Dingo\Api\Http\FormRequest;
use Illuminate\Validation\ValidationException;

class Request extends FormRequest
{
    public function authorize()
    {
        return true;
    }

    protected function failedValidation(Validator $validator)
    {
        if ($this->container['request'] instanceof \Illuminate\Http\Request) {
            throw new ResourceException($validator->errors()->first(), $validator->errors());
        }

        throw (new ValidationException($validator))
            ->errorBag($this->errorBag)
            ->redirectTo($this->getRedirectUrl());
    }
}

其他所有的 request 文件都继承该基类

<?php

namespace App\Http\Requests;

class PostRequest extends Request
{
    public function attributes()
    {
        return [
            'title' => "标题",
        ];
    }

    public function rules()
    {
        switch ($this->method()) {
            case 'PUT':
                return [
                    'title' => 'required'
                ];
            case 'POST':
                return [
                    'title' => 'required'
                ];
            default:
                return [];
        }
    }
}

最后出现的422提示格式

{
    "message": "必须指定:标题",
    "status_code": 422,
    "errors": {
        "title": [
            "必须指定:标题"
        ]
    }
}
本作品采用《CC 协议》,转载必须注明作者和本文链接
《L01 基础入门》
我们将带你从零开发一个项目并部署到线上,本课程教授 Web 开发中专业、实用的技能,如 Git 工作流、Laravel Mix 前端工作流等。
《L04 微信小程序从零到发布》
从小程序个人账户申请开始,带你一步步进行开发一个微信小程序,直到提交微信控制台上线发布。
讨论数量: 2

https://github.com/overtrue/laravel-lang
这个包你可以看一下

5年前 评论
ejellyfish 4年前

谢谢,422提示的处理帮大忙了 :see_no_evil:

4年前 评论

讨论应以学习和精进为目的。请勿发布不友善或者负能量的内容,与人为善,比聪明更重要!