LoginSignup
0
1

More than 5 years have passed since last update.

PHPで参照foreachした配列をmessagepackでシリアライズするとnullのキーができる問題

Last updated at Posted at 2017-03-15

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でしか試してないので、情報ください。

0
1
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
0
1