pack() and unpack() convert numbers to raw bytes and back, and the order of those bytes is called endianness. Little-endian puts the least significant byte first, while big-endian puts the most significant byte first. PHP lets you pick the byte order for unsigned integers but not for signed ones, meaning numbers that can be negative. This RFC from Alexandre Daubois fixes that by borrowing the < and > modifiers from Perl.
Show me
Here is the RFC's before and after for a signed 4-byte little-endian number:
// Before: a manual workaround $unpackToSignedInt = static function (string $v) { $unpacked = unpack('va/Cb/cc', $v); return ($unpacked['c'] << 24) | ($unpacked['b'] << 16) | $unpacked['a']; }; // After $value = unpack('l<', $binaryData)[1]; // signed little-endian 4-byte
And a few more from the RFC:
$data = pack('s<l<q<', -258, -16909060, -72340172838076673); // little-endian $data = pack('s>l>q>', -258, -16909060, -72340172838076673); // big-endian $data = pack('S<L>Q<', 258, 16909060, 72340172838076673); // unsigned
The new format codes
<means little-endian and>means big-endian.- They work on
s,landq(signed 2, 4 and 8 bytes). - They also work on
S,LandQ(unsigned 2, 4 and 8 bytes), sopack('S<', 42)produces the same bytes aspack('v', 42). - They don't work on
v,n,V,N,PorJ, which already have a fixed byte order. Using them there throws aValueError. - Any other format code with a modifier also throws a
ValueError. - On 32-bit PHP, the 8-byte codes throw a
ValueError, just asqandQalready do.
The RFC rejected adding new format letters or a brand new function. It says the Perl syntax is already familiar and is the smallest change.
What it means for existing code
Nothing breaks. < and > aren't used in pack format strings today, so your current format strings behave the same.
The vote
It passed 20 to 0, with no abstentions, clearing the two-thirds majority it needed. Voting closed on January 29, 2026. The RFC targets PHP 8.6.