ThinkSNS+ 是如何计算字符显示长度的

什么是ThinkSNS+
  ThinkSNS(简称TS),一款全平台综合性社交系统,为国内外大中小企业和创业者提供社会化软件研发及技术解决方案,目前最新版本为ThinkSNS+、ThinkSNS V4、ThinkSNS【简】。

今天我们来聊一下可能很多人都会头疼的东西:显示长度。

需求是这样的,在字符的显示上,两个英文单词才占一个中文或者其他语言的显示长度。如下:

ab
哈
?

上面排的是两个英文字母,一个汉字,一个Emoji。你会发现,在显示上占的宽度是一致的。一些设计上为了好看也要求有这样的处理。

例如,我们的用户名需求是最多12个非单字节字符或者24个单字节字符的需求也可以混合排的需求,我们写后端不得不处理这样的验证了。

需求规则是 /^[a-zA-Z\x7f-\xff][a-zA-Z0-9\x7f-\xff]*$/

在ThinkSNS+中,为了能把这部分验证公用,所以选择使用自定义验证规则。我们先说下计算的实现思路吧!

首先,就算是mb_strlen也没法准确的获取多字节字符和单子节字符混合在一起的长度,网上有个说法,汉字占三个字节,英文数组半角符号占一个字节,所以:

`(mb_strlen($str) + strleng($str)) / 2`

用这个方法可以得到单字节占0.5多字节占1的计算。但是以中文为例,只有两万个汉字才是这种情况,还有六万多汉字是四个,其次,emoji也是四个字节。根本无法准确的计算。

好在在无意间发现一个奇怪的东西str_word_count 这个函数计算非英文单词外是除了符号例如中文就是按照汉字个数算的,emoji也是同理。

发现这个以后,咱们就好办了。我们吧用户名中的 [a-aA-Z0-9_] 剔除掉,单独计算不就是我们要的验证长度了吗?

所以,首先我们用:

preg_match_all(‘/[a-zA-Z0-9_]/‘, $value, $single);
$single = count($single[0]) / 2;

方式单独计算出单字节字符的显示长度,再用:

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

方式计算出多字节的长度,最后:

$length = $single + $double;

就得出了显示长度,实现了,最后封装成验证规则:

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 = str_word_count(preg_replace(‘([a-zA-Z0-9_])‘, ‘‘, $value));

                        // 得出最终计算字符的长度
            $length = $single + $double;

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

代码是原型代码,还没有进行优化,之后我们只要按照下面的方式用:

$rules = [
    ‘inputKey‘ => ‘display_length:5‘, // 表示 0 - 5 显示长度
    ‘inputkey2’ => ‘display_length:4,12‘ // 表示显示长度为 4 - 12
];

现在就很好的解决了这个需求。

我们很乐意,将基于 Laravel 的 ThinkSNS+ 产品开发中的技术解决方案分享给大家,也希望喜欢的朋友能给国内开源产品一点点的支持。

往期研发日记回顾:

《ThinkSNS+基于?Laravel master?分支【研发日记一】》

《ThinkSNS+研发中前端的抉择(webpack/Vue)踩坑日记【研发日记二】》

《基于?Laravel Route?的?ThinkSNS+ Component【研发日记三】》

《如何做到?Laravel?配置可以网站后台配置【研发日记四】》

开源代码仓库:

GitHub:https://github.com/zhiyicx/thinksns-plus(点击star,每日关注开发动态。)

开源不易,为了争取开源,我们团队做了很多努力。把基于Laravel的作品展示在大家面前,之后专栏会持续不断的分享ThinkSNS +开发过程中的技术细节。

原文地址:https://blog.51cto.com/14231620/2412310

时间: 2024-08-27 19:32:20

ThinkSNS+ 是如何计算字符显示长度的的相关文章

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

什么是ThinkSNS+ ThinkSNS(简称TS)始于2008年,一款全平台综合性社交系统,为国内外大中小企业和创业者提供社会化软件研发及技术解决方案,目前最新版本为ThinkSNS+.ThinkSNS V4.ThinkSNS[简]. 后端框架使用laravel,每周和 laravel master 保持同步,而后台和 html 5 则采用 vue 开发.语言特性方面,采用 php 7 的严格模式. 言归正传,之所以写继篇,其实是来检讨的,上一次发表了<ThinkSNS+?如何计算字符显示长

关于 Overtrue 的拼音库 overtrue/pinyin 为何 travis 为 error

什么是ThinkSNS ? ThinkSNS(简称TS),一款全平台综合性社交系统,为国内外大中小企业和创业者提供社会化软件研发及技术解决方案. 1.png 这是 https://github.com/overtrue/pinyin 首页 README 中的持续集成状态. 之前有朋友问我,这个 travis 状态时 error 能用么?肯定是能用,我们来看下 travis 上什么地方错误了: 2.png 已经显示出来了,其中单元测试失败的是 php 5.5 和 php 5.6 我们随便点击一个进

PHP面试题

1.不用新变量直接交换现有两个变量的值 (1)list($a,$b)=array($b,$a);(2)a=a+b,b=a-b,a=a-b 2.PHP数字金额转大小格式,同时说明思路 function daxie($num){ $da_num = array('零','一','二','三','四','五','六','七','八','九'); $return = ''; $len_num = strlen($num); if(!is_numeric($num) || $len_num < 0){ r

PHP知识大全【基础】

1. 变量如何定义?如何检查变量是否定义?如何删除一个变量?怎样检测变量是否设置? $定义  isset()// 检测变量是否设置 defined()// 检测常量是否设置 unset()//销毁指定的变量 empty()// 检测变量是否为空 2. 什么是可变变量? 一个变量的变量名可以动态的设置和使用. $a = 'hello' , $$a = 'world',  ${$a}=hello world 3. 变量赋值方式有哪几种? 1)直接赋值   2)变量间赋值   3)引用赋值 4. 引用

linux内核调度算法(2)--CPU时间片如何分配 转!

内核在微观上,把CPU的运行时间分成许多分,然后安排给各个进程轮流运行,造成宏观上所有的进程仿佛同时在执行.双核CPU,实际上最多只能有两个进程在同时运行,大家在top.vmstat命令里看到的正在运行的进程,并不是真的在占有着CPU哈. 所以,一些设计良好的高性能进程,比如nginx,都是实际上有几颗CPU,就配几个工作进程,道理就在这.比如你的服务器有8颗CPU,那么nginx worker应当只有8个,当你多于8个时,内核可能会放超过多个nginx worker进程到1个runqueue里

php知识点集合

---------------------------------------------------------           PHP知识大全 --------------------------------------------------------- 1. 变量如何定义?如何检查变量是否定义?如何删除一个变量?怎样检测变量是否设置? $定义   isset()// 检测变量是否设置 defined()// 检测常量是否设置 unset()//销毁指定的变量 empty()// 检

HTTP/1.1中文版

http://www.cnblogs.com/cxd4321/p/3504632.html 摘要 超文本传输协议(HTTP)是一种为分布式,合作式,多媒体信息系统服务,面向应用层的协议.它是一种通用的,不分状态(stateless)的协议,除了诸如名称服务和分布对象管理系统之类的超文本用途外,还可以通过扩展它的请求方式,错误代码和报头来完成许多任务.HTTP的一个特点是数据表示方式的典型性和可协商性允许独立于传输数据而建立系统.在1990年WWW全球信息刚刚起步的时候HTTP就得到了应用.HTT

PHP知识大全

--------------------------------------------------------- --------------------------------------------------------- 1. 变量如何定义?如何检查变量是否定义?如何删除一个变量?怎样检测变量是否设置? $定义   isset()// 检测变量是否设置 defined()// 检测常量是否设置 unset()//销毁指定的变量 empty()// 检测变量是否为空 2. 什么是可变变量

PHP笔试题和面试题

1.不用新变量直接交换现有两个变量的值 (1)list($a,$b)=array($b,$a); (2)a=a+b,b=a-b,a=a-b 2.PHP数字金额转大小格式,同时说明思路 function daxie($num){ $da_num = array('零','一','二','三','四','五','六','七','八','九'); $return = ''; $len_num = strlen($num); if(!is_numeric($num) || $len_num < 0){