继:我朝特有需求之--英文字符占 0.5 个,中文字符占 1 个

博主因网友反馈,用周末时间改进ThinkSNS+字符显示长度计算方法。需求是单字节字符占0.5,多字节字符占1字节。原方法兼容性差,改进后用mb_strlen函数,最终实现Laravel验证规则,代码来自开源程序ThinkSNS+。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

之所以写继篇,其实是来检讨的,上一次发表了《ThinkSNS+ 如何计算字符显示长度》后,有网友几经测试后告知str_word_count 有问题。

根据ThinkSNS+ 的进度安排,最近在研发支付功能,所以只能使用周末的时间做了一个兼容性更好的计算方法。

需求

重新说下需求:在我天朝 PM 经常会提一种要求,就是例如一个用户名最多输入12个汉字,但是英文可以输入24个,混排也要满足这个规则。

简言之:单字节字符占0.5,多字节字符占1字节。

解决

闲下来的时候看了上篇文章中的算法,其实是没什么问题的,只是兼容性不够好,而且写那个方法时想得过于复杂

也不知道当时脑袋里面都想啥了

我们看上一篇中计算多字节的方法:

$double = str_word_count(preg_replace('([a-zA-Z0-9_])', '', $value));

计算方法是剔除我们需求中允许的单字节,然后通过 str word count 来获取多字节的个数,其实这个函数是可以获取到的,但是部分系统下是不会成功的。还有一个函数就可以直接获取多字节的个数 mb strlen 修改后如下:

$double = mb_strlen(preg_replace('([a-zA-Z0-9_])', '', $str));

 然后我们就可以正确完成这个需求了,最终实现的 Laravel 验证规则如下:

/ 添加长度规则Validator::extend('display_length', function ($attribute, $value, array $parameters) {
    if (empty($parameters)) {
        throw new \InvalidArgumentException('Parameters must be passed');
    }

    $min = 0;
    if (count($parameters) === 1) {
        list($max) = $parameters;
    } elseif (count($parameters) >= 2) {
        list($min, $max) = $parameters;
    }

    if (! isset($max) || $max < $min) {
        throw new \InvalidArgumentException('The parameters passed are incorrect');
    }

    // 计算单字节.
    preg_match_all('/[a-zA-Z0-9_]/', $value, $single);
    $single = count($single[0]) / 2;

    // 多子节长度.
    $double = mb_strlen(preg_replace('([a-zA-Z0-9_])', '', $value));

    $length = $single + $double;

    return $length >= $min && $length <= $max;
});

Laravel 通过上面的规则,可以在表单验证规则中直接验证,还支持传入最小值和最大值。

上面的代码都是来自于基于 Laravel 开发的开源程序 ThinkSNS+ 中,ThinkSNS+ 采用 apache-2.0 协议开源,我相信可以作为很多 Laravel 学习者的学习程序之一。

项目地址:GitHub: https://github.com/zhiyicx/thinksns-plus(点击star关注研发动态,感谢大家的支持)

转载于:https://www.cnblogs.com/thinkSNS/p/11051403.html

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值