передать по ссылке — PHP 7 — итеративно заполнить многоуровневый массив в обратном вызове

Мне нужно построить сложный многоуровневый массив только в обратном вызове, одно атомное обновление за вызов.

Причина этому: обратный вызов многократно вызывается из итеративного парсера. Наконец, он должен создать десериализованный PHP-массив анализируемого двоичного формата.

Вот исполняемый код:

const ACTION_VALUE = 1;
const ACTION_ENTER = 2;
const ACTION_LEAVE = 3;

function callback($action, $value, &$param)
{
switch ($action)
{
case ACTION_ENTER:
$param['parent'][] = &$param['current'];
$param['current'][] = [];

end($param['current']);
$param['current'] = &$param['current'][key($param['current'])];
break;

case ACTION_LEAVE:
unset($param['current']);
$param['current'] = array_pop($param['parent']);
end($param['current']);
break;

case ACTION_VALUE:
$param['current'][] = $value;
break;
}
}

// prepare container
$arr = [];
$arr['data'] = [];
$arr['current'] = &$arr['data'];
$arr['parent'] = [];

// callback invocations
callback(ACTION_VALUE, 1, $arr);
callback(ACTION_VALUE, 2, $arr);
callback(ACTION_ENTER, 0, $arr);
callback(ACTION_VALUE, 10, $arr);
callback(ACTION_VALUE, 11, $arr);
callback(ACTION_LEAVE, 0, $arr);
callback(ACTION_VALUE, 3, $arr);
callback(ACTION_VALUE, 4, $arr);

// now see result
var_dump(json_encode($arr['data']));

Попытайся Вот

Над примером печатает:

[1,2,[10,11]], но должен
[1,2,[10,11],3,4],

Обновить:
Многоуровневый означает произвольные массивы случайной глубины.

Обновить:
Проблема была с array_pop()см. ниже принятый ответ для фиксированной версии.

0

Решение

Я думаю проблема в том array_pop который не возвращает фактическую ссылку на последний элемент. Этот работает:

<?php

const ACTION_VALUE = 1;
const ACTION_ENTER = 2;
const ACTION_LEAVE = 3;

function callback($action, $value, &$param)
{
switch ($action) {
case ACTION_ENTER:
$param['parent'][] = &$param['current'];
$param['current'][] = [];

end($param['current']);
$param['current'] = &$param['current'][key($param['current'])];
break;

case ACTION_LEAVE:
unset($param['current']);
end($param['parent']);
$param['current'] = &$param['parent'][key($param['parent'])];
unset($param['parent'][key($param['parent'])]);
end($param['current']);
break;

case ACTION_VALUE:
$param['current'][] = $value;
break;
}
}

// prepare container
$arr = [];
$arr['data'] = [];
$arr['current'] = &$arr['data'];
$arr['parent'] = [];

// callback invocations
callback(ACTION_VALUE, 1, $arr);
callback(ACTION_VALUE, 2, $arr);
callback(ACTION_ENTER, 0, $arr);
callback(ACTION_VALUE, 10, $arr);
callback(ACTION_VALUE, 11, $arr);
callback(ACTION_ENTER, 0, $arr);
callback(ACTION_VALUE, 40, $arr);
callback(ACTION_VALUE, 41, $arr);
callback(ACTION_LEAVE, 0, $arr);
callback(ACTION_LEAVE, 0, $arr);
callback(ACTION_VALUE, 3, $arr);
callback(ACTION_VALUE, 4, $arr);

// now see result
var_dump(json_encode($arr['data']));
1

Другие решения

Вы можете сделать что-то вроде этого, это определенно упрощает то, что вы пытаетесь сделать. У него просто разные значения базового массива, но он достаточно похож, поэтому я думаю, что он должен работать для вашего приложения.

Внесенные изменения: реструктурировали массив и использовали addTo строка как указатель

const ACTION_VALUE = 1;
const ACTION_ENTER = 2;
const ACTION_LEAVE = 3;

// prepare container
$arr = [];
$arr['data'] = [];
$arr['addTo'] = 'data';
$arr['temp'] = [];

function callback($action, $value, &$param)
{
switch ($action)
{
case ACTION_ENTER:
$param['addTo'] = 'temp';
break;

case ACTION_LEAVE:
$param['addTo'] = 'data';
$param['data'][] = $param['temp'];
$param['temp'] = [];
break;

case ACTION_VALUE:
$param[$param['addTo']][] = $value;
break;
}
}



// callback invocations
callback(ACTION_VALUE, 1, $arr);
callback(ACTION_VALUE, 2, $arr);
callback(ACTION_ENTER, 0, $arr);
callback(ACTION_VALUE, 10, $arr);
callback(ACTION_VALUE, 11, $arr);
callback(ACTION_LEAVE, 0, $arr);
callback(ACTION_VALUE, 3, $arr);
callback(ACTION_VALUE, 4, $arr);

// now see result
var_dump(json_encode($arr['data']));
2

По вопросам рекламы [email protected]