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,每日关注开发动态。)
ThinkSNS+ 是如何计算字符显示长度的的更多相关文章
- 【社交系统研发日记五】ThinkSNS+如何计算字符显示长度?
今天我们来聊一下可能很多人都会头疼的东西:显示长度. 需求是这样的,在字符的显示上,两个英文单词才占一个中文或者其他语言的显示长度.如下: 上面排的是两个英文字母,一个汉字,一个Emoji.你会发现, ...
- 社群系统 ThinkSNS+ 中如何利用 Laravel 表单验证来验证用户名的?(我朝独有需求,两个字母占一个汉字。。。)
ThinkSNS+后端框架使用laravel,每周和 laravel master 保持同步,而后台和 html 5 则采用 vue 开发.语言特性方面,采用 php 7 的严格模式. 言归正传,之所 ...
- PHP计算字符串长度,PHP如何计算短信的长度/字数?
PHP计算字符串长度,包括计算英文.GBK.UTF-8多种字符集下PHP如何计算字符串长度. 英文字符串长度,strlen()是PHP自带的计算英文字符串的函数. GBK字符串长度 中文字符计算为2个 ...
- 记一次js中和php中的字符串长度计算截取的终极问题和完美解决方案
1.js是用unicode算长度的,比如单字节的算1,中文也算1,但是正常我们想让两个单字节算1,如何计算这个长度 第一种解决方案,用正则,如下 /[\u0x00-\u0xff]/,天真的想着,这样就 ...
- (SqlServe)关于字符串长度被截断的问题
1. 问题描述 在同步数据时常常会发现一个错误:将截断字符串或二进制数据. 2. 问题原因 这个问题出现的原因是:要插入的数值字段的长度超出了数据库中字段的长度.比如:插入的字符串字节长度是40,数据 ...
- HTTP超文本传输协议-HTTP/1.1中文版
摘要 超文本传输协议(HTTP)是一种为分布式,合作式,多媒体信息系统服务,面向应用层的协议.它是一种通用的,不分状态(stateless)的协议,除了诸如名称服务和分布对象管理系统之类的超文本用途外 ...
- linux内核调度算法(2)--CPU时间片如何分配 转!
http://blog.csdn.net/russell_tao/article/details/7103012 内核在微观上,把CPU的运行时间分成许多分,然后安排给各个进程轮流运行,造成宏观上所有 ...
- Erlang之父的学习历史及学习建议
当我开始学习编程的时候(1967年),我可以在 FORTRAN 和(传说中的)Algol 之间选择,不过没有任何人了解 Algol,所以我选择了 FORTRAN. 在我最早学习编程的时候,我的编程周期 ...
- php知识点集合
--------------------------------------------------------- PHP知识大全 ------------------------ ...
随机推荐
- [STM8L]基于STM8L152的TAB段式LCD液晶驱动的分析 - 单片机干货 - 中国电子技术论坛 - 最好最受欢迎电子论坛!
[STM8L]基于STM8L152的TAB段式LCD液晶驱动的分析 - 单片机干货 - 中国电子技术论坛 - 最好最受欢迎电子论坛!.md 主控芯片为STM8L152C4T6自带LCD控制器,低功耗系 ...
- 20145239杜文超 《Java程序设计》第7周学习总结
20145239 <Java程序设计>第7周学习总结 教材学习内容总结 Lambda 认识Lambda语法 Lambda语法概述: Arrays的sort()方法可以用来排序,在使用sor ...
- debian7 amd64版本添加对x86包的支持
dpkg --add-architecture i386apt-get updateapt-get install ia32-libs ia32-libs-gtk
- HDU4511 小明系列故事——女友的考验 —— AC自动机 + DP
题目链接:https://vjudge.net/problem/HDU-4511 小明系列故事——女友的考验 Time Limit: 500/200 MS (Java/Others) Memor ...
- Zabbix监控华为交换机
一. 监控交换机首先要在交换机开通snmp协议. 有两种方式开通,web界面,及交换机的配置界面 Web界面开通: 交换机配置界面 有web界面的,使用web界面相对简单,本项目就是用web界面 ...
- TCP协议与流通信
作者:Vamei 出处:http://www.cnblogs.com/vamei 欢迎转载,也请保留这段声明.谢谢! TCP(Transportation Control Protocol)协议与IP ...
- k8s-应用快速入门(ma)
[root@k8s-master ~]# kubectl run nginx-deploy --image=nginx:1.14-alpine --port=80 --replicas=1 deplo ...
- CodeForces - 204C Little Elephant and Furik and Rubik
CodeForces - 204C Little Elephant and Furik and Rubik 个人感觉是很好的一道题 这道题乍一看我们无从下手,那我们就先想想怎么打暴力 暴力还不简单?枚 ...
- 详解使用python crontab设置linux定时任务
熟悉linux的朋友应该知道在linux中可以使用crontab设置定时任务.可以通过命令crontab -e编写任务.当然也可以直接写配置文件设置任务. 但是有时候希望通过脚本自动设置,比如我们应用 ...
- tyvj1015公路乘车——DP
题目:http://www.joyoi.cn/problem/tyvj-1015 代码如下: #include<iostream> #include<cstdio> using ...