news 2026/10/24 4:50:53

PHP strlen()函数用法详解

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
PHP strlen()函数用法详解

前言


strlen()返回字符串的字节数。注意,手册里写的是字节数,不是字符数——这是关于它最需要记住、也最容易出错的一点。


最常见的症状是:一段中文昵称,肉眼数着是 4 个字,strlen()却报 12。「长度校验怎么总是提前触发」这类问题,根子几乎都在这里。原因是 UTF-8 编码下一个常用汉字占 3 个字节,strlen()老老实实地把 12 个字节数了出来。


第二个常见误解方向正好相反:有人担心strlen()会遍历整个字符串所以「很慢」,于是写出一堆手动缓存长度的代码。这也是错的。PHP 的字符串是「长度 + 字节内容」的结构(所以它是二进制安全的),长度就存在结构体里,strlen()不需要扫描内容,它的开销与字符串长度无关。


本文讲清strlen()的签名与返回值、字节与字符的区别、如何正确截断中文字符串、以及在使用长度函数时该选哪一个。


一、签名与返回值


以 PHP 官方手册为准:


strlen(string $string): int



项目说明



参数任意字符串,二进制安全,内容里含\0也不会被截断

返回字节数,类型 int;空字符串返回0

失败正常情况不会失败,返回值恒为 int(不会返回false)

版本提示PHP 8.1 起,向非可空参数传null会触发废弃提示

非字符串入参PHP 8 起传入数组会抛TypeError



字节与字符的差异,用一张表最直观:




字符串strlen()mb_strlen($s, 'UTF-8')



'abc'33

'你好'62

'中文abc'95

''00



<?php
// 适用于 PHP 8.0+

var_dump(strlen('abc')); // int(3)
var_dump(strlen('你好')); // int(6) 两个汉字,每个 3 字节
var_dump(strlen('中文abc')); // int(9) 6 + 3
var_dump(strlen('')); // int(0)

// PHP 7.0 起支持 \u{} 转义,可以直接写出码位
$emoji = "\u{1F600}";
var_dump(strlen($emoji)); // int(4) UTF-8 下该码位占 4 字节
var_dump(mb_strlen($emoji, 'UTF-8')); // int(1) 但只算一个字符

mb_strlen()属于 mbstring 扩展(mbstring是常用扩展,但不保证一定编译进来,可以用extension_loaded('mbstring')检查)。它接收第二个参数指定编码,建议永远显式传'UTF-8',而不是依赖mb_internal_encoding()的当前设置——那个设置可能被框架、被 ini 文件、被别的代码改掉,一旦不是 UTF-8,mb_strlen()的结果会跟着变,这类 bug 极难复现。


二、什么时候用 strlen,什么时候用 mb_strlen


判断依据只有一个:约束是「字节」还是「字符」。




场景该用哪个原因



校验昵称、标题的字数上限mb_strlen($s, 'UTF-8')用户感知的是「几个字」

对齐 MySQLvarchar(20)的长度mb_strlen($s, 'UTF-8')varchar的长度按字符计

对齐varbinary/blob列strlen($s)二进制列按字节计

校验写入文件、发送到 socket 的数据量strlen($s)传输层按字节算

缓存键长度、队列消息体大小限制strlen($s)通常按字节限制

判断字符串是否为空$s === ''最直接,不涉及函数调用



一句话总结:面向人的长度用mb_strlen(),面向机器(存储、传输、协议)的长度用strlen()。把这两条对齐清楚,「长度校验总是差几倍」的问题就不会再出现。


<?php
// 适用于 PHP 8.0+

function validateNickname(string $nickname, int $maxChars = 10): bool
{
// 业务约束是「不超过 10 个字」,所以必须按字符数判断
return mb_strlen($nickname, 'UTF-8') <= $maxChars;
}

var_dump(validateNickname('你好世界')); // bool(true) 4 个字
var_dump(validateNickname('你好世界你好世界你好世界')); // bool(false) 12 个字,超过上限 10

不要写成strlen($nickname) <= 10——那样一个汉字会被算成 3 个,用户打 4 个字就被判定超长。


三、按长度截断中文字符串


substr()是按字节切的,用它截断 UTF-8 字符串会切出「半个汉字」,产生一段无效字节序列。


<?php
// 适用于 PHP 8.0+

$s = '你好世界';

// 按字节切:长度看起来没错,内容却是坏的
$cut = substr($s, 0, 4);
var_dump(strlen($cut)); // int(4)
var_dump(mb_check_encoding($cut, 'UTF-8')); // bool(false) 这 4 字节不是合法 UTF-8

// 按字符切:正确
$ok = mb_substr($s, 0, 2, 'UTF-8');
var_dump($ok); // string(6) "你好"
var_dump(strlen($ok)); // int(6) 2 个字符,6 个字节

// 按字节切但保证不切坏字符:mb_strcut()
$byteCut = mb_strcut($s, 0, 4, 'UTF-8');
var_dump($byteCut); // string(3) "你"
var_dump(mb_check_encoding($byteCut, 'UTF-8')); // bool(true)

三个函数的区别值得单独记一下:




函数计量单位超长时的行为



substr($s, $start, $length)字节可能切出半个字符,产生无效编码

mb_substr($s, $start, $length, 'UTF-8')字符按字符边界切割,结果始终合法

mb_strcut($s, $start, $length, 'UTF-8')字节按字节算长度,但不会切断字符



用法上:「最多显示 20 个字」用mb_substr();「这个字段最多 30 字节」用mb_strcut()。两者都能保证结果仍是合法的 UTF-8,不会给后续的json_encode()制造麻烦——json_encode()遇到无效 UTF-8 会直接返回false,这是乱码截断之后最常见的连锁事故。


四、长度函数的选型


PHP 里数长度的函数不止一个,各有明确的适用面:




函数计数单位所属扩展典型用途



strlen()字节核心二进制数据、协议、存储限制

mb_strlen()字符(按编码)mbstring面向用户的字数校验

iconv_strlen()字符(按编码)iconv同上,未安装 mbstring 时的替代

grapheme_strlen()字素簇intl需要「用户感知的一个字符」时,如组合字符、部分 emoji 序列

count()元素个数核心数组、Countable对象



grapheme_strlen()是这条线上的终点:有些字符由多个码位组合而成(比如带变音符号的字母、由多个码位组成的 emoji 序列),mb_strlen()会把它们算成好几个,而用户看起来只有一个。如果业务真的要求「所见即所得」的字符数,需要 intl 扩展提供的grapheme_strlen()。


反过来也要强调一句边界:strlen()不能用来数数组的元素个数。count()才是干这个的,而且 PHP 8 起把数组传给strlen()会直接抛TypeError(PHP 7 只是返回null并发出警告),这个改动把一个静默的错误变成了显式的崩溃,对排查反而更友好。


常见坑点



  • ❌ 用strlen()校验中文字数:if (strlen($nickname) > 10)。✅ 一个汉字占 3 字节,应该用mb_strlen($nickname, 'UTF-8')。

  • ❌ 用substr()截断中文或 emoji,结果出现乱码,后面json_encode()还失败了。✅ 按字符切用mb_substr(),按字节切又不切坏字符用mb_strcut()。

  • ❌ 担心strlen()慢,于是到处手动缓存长度。✅ PHP 字符串自带长度字段,strlen()不扫描内容,开销与长度无关。

  • ❌ 调用mb_strlen()不传编码,默默依赖mb_internal_encoding()。✅ 显式写mb_strlen($s, 'UTF-8'),避免被 ini 或框架改动影响。

  • ❌ 把数组传给strlen()。✅ PHP 8 起抛TypeError;要数元素个数用count()。

  • ❌ 用strlen($s) === false判断字符是否为空。✅strlen()恒返回 int,空串就是0;判空直接写$s === ''。

  • ❌ 用strlen()校验数据库varchar字段的长度上限。✅varchar按字符计,要用mb_strlen()对齐;只有varbinary、blob之类才按字节算。

  • ❌ 向strlen()传null(读取未定义的参数时很可能发生)。✅ PHP 8.1 起该用法被废弃,先进判断再传,或用(string) $v显式转换。


总结




需求正确写法备注



字节数strlen($s)二进制安全,内容含\0也不截断

字符数mb_strlen($s, 'UTF-8')需要 mbstring 扩展

字素簇数量grapheme_strlen($s)需要 intl 扩展

按字符截断mb_substr($s, 0, $n, 'UTF-8')结果始终是合法 UTF-8

按字节安全截断mb_strcut($s, 0, $n, 'UTF-8')不切断字符

判断非空$s !== ''比strlen($s) > 0更直接

数数组元素count($arr)strlen()不能用于数组

校验合法性mb_check_encoding($s, 'UTF-8')用于确认截断后是否仍然合法



strlen()的全部要点就是一句话:它数的是字节,而且是不扫描内容地数。想清楚业务约束究竟是「几个字」还是「多少字节」,再对应地选mb_strlen()或者strlen(),中文环境下的长度问题基本就绝迹了;截断字符串时记得用mb_substr()或mb_strcut(),别让半个汉字流到下游去。





版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/10/23 22:14:07

上了 AGV 人效却没动:一次企业 AI 落地复盘,以及 FDE 的真实工作结构

摘要&#xff1a;一场从业者群聊里&#xff0c;有人用自家工厂的真实改造给出了完整答案——问题从来不在模型&#xff0c;而在计价规则、利益重构和预期管理。本文整理了这场讨论中最有价值的五个判断&#xff0c;包含四方激励逆冲模型、三个零硬件改造动作&#xff0c;以及一…

作者头像 李华
网站建设 2026/10/24 2:11:25

基于Flask的新农村自建房改造管理系统设计与部署实践

前阵子接了一个挺接地气的项目&#xff1a;给乡镇做一套基于 Python Flask 的新农村自建房改造管理系统&#xff0c;内部编号就叫 s4z085o6。刚听到需求的时候&#xff0c;我以为这不过是又一个“XX管理系统”的例行重复&#xff0c;后来深入聊完才发现&#xff0c;基层对这类系…

作者头像 李华
网站建设 2026/10/23 11:29:21

三级网络技术实战排错:OSPF、ARP、TCP故障诊断手册

简介&#xff1a;本资源是一份面向计算机等级考试三级网络技术考生及初学者的系统性知识点精要总结&#xff0c;聚焦计算机硬件体系、软件工程基础、多媒体技术原理与计算机网络演进脉络四大核心模块。内容覆盖计算机四大特性、五阶段发展史、性能指标&#xff08;MIPS/MFLOPS、…

作者头像 李华
网站建设 2026/10/13 23:00:20

从零搭建你的 A 股量化系统(四十六):VaR 与 CVaR——散户版风险度量实操(附代码与图)

系列名:《从零搭建你的 A 股量化系统》| 专栏 S4 金融理论 | 第 5 篇 / 共 16 篇 | T1 度量层 标签:#量化投资 #金融理论 #VaR #CVaR #风险度量 #厚尾 #GARCH #A股 #散户 上篇(S4-004)把「过去的风险」拆成了四块:最大回撤管亏得多深、水下曲线管套了多久、Calmar 算回…

作者头像 李华
网站建设 2026/10/14 4:21:29

2026 Turnitin 查重和 AI 检测都不过?一站式降AIGC软件实测推荐

一、前言&#xff1a;2026 高校论文审核新难题 随着高校学术审核体系不断升级&#xff0c;知网、维普等主流检测平台全面上线AIGC 智能检测功能&#xff0c;当代毕业生的论文写作与修改迎来双重考验。以往论文仅需攻克重复率超标问题&#xff0c;如今还要规避AI写作痕迹检测风险…

作者头像 李华
网站建设 2026/10/14 15:43:46

AD使用前设置

①提前设置编译报错&#xff1a;点击左上角项目PrjPcb右键得到Project Options&#xff0c;(1)解决虚接&#xff1a;在violation associated with net中将Floating net labels 和Floating power objects改为致命错误 (2)解决单端网络&#xff1a;在violation associated …

作者头像 李华