PHPとスマートフォンアプリとの通信でmessagepackを使っていて変な現象に見舞われたのでメモ
配列下の配列を直接foraechで参照渡しをすると、messagepackでpackした時にnullのキーが出来上がる。
環境
PHP:7.0.12
pecl-msgpack:2.0.1
#テストコード
messagepack_test.php
<?php
/**
* バイナリダンプ
* @param $data
* @return string
*/
function bin_dump($data)
{
$result = '';
$binary = unpack("C*", $data);
foreach ($binary as $v) {
$result .= sprintf("%02x ", $v);
}
return $result;
}
/**
* @param $message
*/
function write_line($message)
{
echo $message . PHP_EOL;
}
/**
* 出力
* @param $array
*/
function output($array)
{
var_dump($array);
write_line(json_encode($array));
write_line(bin_dump(msgpack_pack($array)));
write_line(json_encode(msgpack_unpack(msgpack_pack($array))));
}
write_line("-----------------------------------------------");
//普通の配列
$array = array(1);
output($array);
write_line("------------------");
//参照foreach後
foreach ($array as &$row) {} unset($row);
output($array);
write_line("-----------------------------------------------");
//配列下の配列
$array = array(array(1));
output($array);
write_line("------------------");
//参照foreach後
foreach ($array[0] as &$row) {} unset($row);
output($array);
write_line("-----------------------------------------------");
//連想配列下の配列
$array = array("x" => array(1));
output($array);
write_line("------------------");
//参照foreach後
foreach ($array["x"] as &$row) {} unset($row);
output($array);
write_line("-----------------------------------------------");
#出力
普通の配列 | 入力 | 参照foreach後 |
---|---|---|
var_dump | array(1){[0]=> int(1)} | array(1){[0]=> int(1)} |
json_encode | [1] | [1] |
msgpack_pack | 91 01 | 91 01 |
pack→unpack→json | [1] | [1] |
配列下の配列 | 入力 | 参照foreach後 |
---|---|---|
var_dump | array(1){[0]=> array(1){[0]=> int(1)}} | array(1){[0]=> array(1){[0]=> int(1)}} |
json_encode | [[1]] | [[1]] |
msgpack_pack | 91 91 01 | 91 82 c0 01 00 01 |
pack→unpack→json | [[1]] | [[1]] |
連想配列下の配列 | 入力 | 参照foreach後 |
---|---|---|
var_dump | array(1){["x"]=> array(1){[0]=> int(1)}} | array(1){["x"]=> array(1){[0]=> int(1)}} |
json_encode | {"x":[1]} | {"x":[1]} |
msgpack_pack | 81 a1 78 91 01 | 81 a1 78 82 c0 01 00 01 |
pack→unpack→json | {"x":[1]} | {"x":[1]} |
配列下の配列と連想配列下の配列を、直接参照foraechするとnullのキーが入ってしまう。
出力のmessagepackをjsonでかくとこう。
配列下の配列
[
{
null: 1,
0: 1
}
]
連想配列下の配列
{
"x": {
null: 1,
0: 1
}
}
phpでpackしたものをphpでunpackする場合はちゃんと戻ってる。
forなりキーなりで更新して参照渡ししなければ大丈夫そう。
foreach ($array["x"] as $key => $row) {
$array["x"][$key] = 2;
}
今のところPHP7.0+msgpack2.0.1でしか試してないので、情報ください。