pack() and unpack() format PHP values into binary strings and back. Hex conversion is only one format code (H/h). Use them when you need structured binary layouts — integers, machine words, mixed records — not as a vague substitute for every string helper.
For plain hex ↔ text, prefer hex2bin/bin2hex. Online: Hex to String · String to Hex.
Mental model
<?php
// pack: values → binary string
// unpack: binary string → array of values
$bin = pack('C*', 0x48, 0x65, 0x6c, 0x6c, 0x6f);
echo $bin; // Hello
print_r(unpack('C*', $bin));
Hex with H / h
<?php
echo pack('H*', '48656c6c6f'); // Hello (high nibble first — usual)
echo pack('h*', '84656c6c6f'); // nibble order swapped — rarely what you want
echo unpack('H*', 'Hello')[1]; // 48656c6c6f
H* matches hex2bin for typical even-length hex. Prefer hex2bin/bin2hex when hex is the only goal — clearer intent and better errors on PHP 8.
Useful non-hex formats
<?php
// unsigned chars
$packet = pack('C3', 1, 2, 255);
// 32-bit unsigned big-endian (network order)
$be = pack('N', 0x01020304);
// 32-bit unsigned little-endian
$le = pack('V', 0x01020304);
// null-terminated string + byte
$rec = pack('a*C', 'id', 7);
Endianness bugs are common. Match the protocol or file format exactly (n/N/v/V, or machine-dependent i/l only when intentional).
Parsing a tiny binary header
<?php
// magic(2) + version(1) + length(2 BE) + payload
$buf = pack('a2Cn', 'HX', 1, 5) . 'hello';
$parts = unpack('a2magic/Cversion/nlength', $buf);
$payload = substr($buf, 5, $parts['length']);
// magic=HX, version=1, length=5, payload=hello
Practical rules
- Do not use
pack('H*')as a “more professional”hex2bin— use the dedicated function. - Always document endianness next to format strings.
- Validate lengths before
unpack; short buffers yield incomplete arrays. - For storage, keep binary as binary (BLOB). Hex is for display and transport edges.
Related: hex2bin() · string to hex · hex encoding overview.