laravel 校验规则 Rule::in 等对中文字符不友好的问题

这个问题应该很多小伙伴都遇到过。记得以前处理过,然而时间太久忘记了,今天又遇到索性就记录一下。
问题发现:

    /**
     * Test Rule::in
     * @param Request $request
     * @return \Illuminate\Http\JsonResponse
     */
    public function index(Request $request)
    {
        if ($error = HttpService::validate($request->all(), [
            'sex' => 'required|string|in:男,女',
        ])) {
            return HttpService::success($error);
        }

        //...

        return HttpService::success('OK');
    }

会发现,无论你 sex 传 “男”还是”女”都提示是无效的。仔细检查下代码,并无问题。为什么过不了校验,?来看看 Validator 到底做了什么吧。
代码追溯:

laravel 校验规则 Rule::in 等对中文字符不友好的问题

laravel 校验规则 Rule::in 等对中文字符不友好的问题

laravel 校验规则 Rule::in 等对中文字符不友好的问题

laravel 校验规则 Rule::in 等对中文字符不友好的问题

直到看到这里就基本明白了, 毕竟这个坑以前解决过。函数:str_getcsv(), 说明:以 CSV 字段格式解析字符串输入,并返回包含读取字段的数组,更多参考PHP手册。
测试函数 str_getcsv() 对中文字符的支持, php artisan tinker:

        $strArr = ['男,女', '男男,女女', '男男,女女女', '女女女,男男'];
        foreach ($strArr as $str) {
            dump(str_getcsv($str));

            $str = iconv("UTF-8", "GBK", $str);
            $arr = str_getcsv($str);
            foreach ($arr as $k => $v) {
                $arr[$k] = iconv('GBK', 'UTF-8', $v);
            }
            dump($arr);
        }

运行结果是不一致,我的php版本是7.4.1。建议感兴趣的多测试几个php版本,估计会有更多收获。

解决方法:

return str_getcsv($parameter);    //改:return explode(',', $parameter);

或者你也可以对 str_getcsv() 进行字符编码处理,具体代码见上测试代码。
PS:原则问题,请勿在vendor依赖库文件进行修改。请使用:php artisan make:rule strIn

本作品采用《CC 协议》,转载必须注明作者和本文链接
《L02 从零构建论坛系统》
以构建论坛项目 LaraBBS 为线索,展开对 Laravel 框架的全面学习。应用程序架构思路贴近 Laravel 框架的设计哲学。
《L01 基础入门》
我们将带你从零开发一个项目并部署到线上,本课程教授 Web 开发中专业、实用的技能,如 Git 工作流、Laravel Mix 前端工作流等。
讨论数量: 10
翟宇鑫

我感觉出发点就有点问题,性别传参无论如何不应该设为「男 & 女」

3年前 评论
她来听我的演唱会 3年前
Diego_crazy (楼主) 3年前
fatrbaby
  1. 不能改vendor里面的东西
  2. 性别一般不会用汉字作为值,0/1足矣
  3. 归根结底还是因为php没有原生支持unicode的原因
3年前 评论
Diego_crazy (楼主) 3年前
sanders

直接换成静态方法调用试试

use Illuminate\Validation\Rule;

    /**
     * Test Rule::in
     * @param Request $request
     * @return \Illuminate\Http\JsonResponse
     */
    public function index(Request $request)
    {
        if ($error = HttpService::validate($request->all(), [
            'sex' => ['required','string',Rule::in(['男','女']),],
        ])) {
            return HttpService::success($error);
        }

        //...

        return HttpService::success('OK');
    }
3年前 评论
Diego_crazy (楼主) 3年前
hcl109080 3年前

file

# php -v 
PHP 8.0.15 (cli) (built: Jan 21 2022 04:34:55) ( NTS )
Copyright (c) The PHP Group
Zend Engine v4.0.15, Copyright (c) Zend Technologies
    with Xdebug v3.1.1, Copyright (c) 2002-2021, by Derick Rethans
    with Zend OPcache v8.0.15, Copyright (c), by Zend Technologies
3年前 评论

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