PHP 8.6 的 pack/unpack 端序修饰符:一个 l(大端)修饰符,直接写在格式码后面。
哪些格式码支持
整数码 s、l、q(有符号)与 S、L、Q(无符号)现在可以带端序修饰符;浮点码 f、d 同样支持。
对本身带固有端序的格式码使用这些修饰符会抛 ValueError,例如网络序的 n、v 这类码再追加 `` 就没有意义。
以前的写法
读一个带符号的小端 int32,得先按无符号读取,再自己判断符号位并做减法:
$v = unpack('V', $raw)[1];
if ($v >= 0x80000000) {
$v -= 0x100000000;
}
这只覆盖了 int32 一种宽度。换成 int64 就要改常量、改判断边界;字段一多,每个字段都得配一段位移和符号修正的代码,解析函数很容易写成一串特判。读一个有符号小端 int32,过去需要多次 unpack 再位移。
现在的写法
$raw = "\x01\x00\x00\x00"; // 小端 int32 = 1
var_dump(unpack('l 1]
var_dump(unpack('l 1]
浮点:
$bytes = "\x00\x00\x80\x3f"; // 小端 float 1.0
var_dump(unpack('f', 1.5);
pack('s', 1.5) 得到大端双精度。同一套修饰符在读写两侧通用,往返测试时不用再手写转换函数。
容易出错的地方:名字后缀会覆盖修饰符
注意键名规则的变化:unpack('s 1]
unpack('l 1]
如果代码里按 `$row[' int(1) }
验证不支持组合的错误类型:
```bash
php -r 'try { unpack("ngetMessage(); }'
验证读写往返:
php -r 'var_dump(bin2hex(pack("s<", -2)));' # feff
php -r 'var_dump(unpack("s<", pack("s<", -2))[1]);' # -2
同一版本的其他变更
PHP 8.6 还包含:clamp()、Time\Duration、Io\Poll、结构化流错误(StreamError 与 StreamErrorMode::Exception)、TLS 会话恢复与 0-RTT、readonly 属性默认值、PASSWORD 相关调整,以及 Session 默认值收紧。8.6.0 GA 计划在 2026-11-19,RC3 为 2026-10-08。