In PHP development, sometimes we need to package multiple data into binary strings in the specified format, which is convenient for network transmission or file storage. The pack function provided by PHP can achieve this requirement, but it requires passing in complex format strings, and the formats of different scenarios vary greatly. This article will introduce how to use pack function to encapsulate a general packaging function that supports multiple formats to improve the reusability and flexibility of the code.
The basic syntax of pack function is:
string pack(string $format, mixed ...$values)
$format specifies the format, such as C represents unsigned characters, n represents 16-bit big-endian endian endian integer, etc.
$values is data in the corresponding format.
For example, package two unsigned characters and a 16-bit big-endian integer:
$data = pack('CCn', 0x01, 0x02, 0x1234);
The function we want to encapsulate:
Accepts a format string and corresponding array of values.
Automatically package values one by one according to the format string.
Supports common format types and is convenient for expansion.
Handle errors that mismatch parameters and formats.
Example function signature:
function universalPack(string $format, array $values): string
The following is a basic implementation that supports C , n , N , a, etc. formats:
function universalPack(string $format, array $values): string {
$result = '';
$formatLength = strlen($format);
$valueIndex = 0;
for ($i = 0; $i < $formatLength; $i++) {
$char = $format[$i];
$repeat = 1;
// Detect whether there are any duplicates,likea4、C2wait
if (isset($format[$i + 1]) && ctype_digit($format[$i + 1])) {
$repeat = (int)$format[$i + 1];
$i++;
}
for ($r = 0; $r < $repeat; $r++) {
if (!isset($values[$valueIndex])) {
throw new InvalidArgumentException("The number of values does not match the format");
}
$value = $values[$valueIndex];
$valueIndex++;
switch ($char) {
case 'C': // Unsigned characters
$result .= pack('C', $value);
break;
case 'n': // 16Bit big endian byte order
$result .= pack('n', $value);
break;
case 'N': // 32Bit big endian byte order
$result .= pack('N', $value);
break;
case 'a': // NULFill string,Length byrepeatDecide
if ($repeat < 1) {
throw new InvalidArgumentException("aThe format needs to be specified in length");
}
$str = str_pad(substr($value, 0, $repeat), $repeat, "\0");
$result .= $str;
// aFormat processing all at oncerepeat,valueIndexNo increment
$valueIndex--;
break;
default:
throw new InvalidArgumentException("Unsupported format characters: $char");
}
}
}
return $result;
}
Suppose you want to package a data packet, the structure is:
1 byte command number ( C )
2 byte data length ( n )
4 byte data ID ( N )
10 byte data content (string, a10 )
Call example:
$command = 0x01;
$length = 14;
$dataId = 123456;
$content = "hello";
$packed = universalPack('CnNa10', [$command, $length, $dataId, $content]);
echo bin2hex($packed);
The output is:
01000e0001e24068656c6c6f0000000000
Pack functions are very powerful, but the format and value are prone to errors when used directly.
Encapsulate a universal universalPack function to simplify the packaging of multi-format data.
Functions can continue to be enhanced according to actual needs, such as supporting more formats, supporting small-endian order, etc.
In actual projects, the unpack function can also be combined with the unpack function to achieve peer unpacking function.