У меня есть данные json в таком файле abc.json.
{
"meta": {
"code": 200,
"requestId": "5afd9043dd57977f0f88d3b1"
},
"response": {
"categories": [
{
"id": "1",
"categories": [
{
"id": "a",
"categories": []
},
{
"id": "b",
"categories": [
{
"id": "c",
"categories": []
},
{
"id": "d",
"categories": [{
"id": "e",
"categories": []
},
{
"id": "f",
"categories": []
}
]
}
]
}
]
} ,
{
"id": "2",
"categories": [
{
"id": "i",
"categories": []
},
{
"id": "j",
"categories": [
{
"id": "k",
"categories": []
},
{
"id": "l",
"categories": []
}
]
}
]
}
]
}
}
В коде PHP я хочу перейти от дочернего к родительскому. Например:
if `$child = c`, then
$categoryString = '1,b,c';
If `$child = i`, then $categoryString = '2,i';
Как я могу этого добиться?
Я пробовал что-то вроде этого: -
function displayRec($a, $parent = "0") {
if (!empty($a['childs'])) {
foreach($a['childs'] as $child) {
displayRec($child, $a['id']);
}
}
}
foreach($navArray as $a) {
displayRec($a);
}
Почему не рекурсивность?
Используйте json_decode, чтобы декодировать json в массивы, а затем используйте цикл, если вложенность ограничена или рекурсивность, как сказала Фани, если существует неограниченное количество уровней вложенности. php.net/manual/en/function.json-decode.php






Я предоставил функцию, которая ищет определенный $childId или «точку входа», чтобы начать движение вверх, пока все родители не будут посещены рекурсивно. При движении вверх он вставляет найденный идентификатор в $result.
Я надеюсь, это поможет вам:
$json = json_decode('{ "meta": { "code": 200, "requestId": "5afd9043dd57977f0f88d3b1" }, "response": { "categories": [ { "id": "1", "categories": [ { "id": "a", "categories": [] }, { "id": "b", "categories": [ { "id": "c", "categories": [] }, { "id": "d", "categories": [{ "id": "e", "categories": [] }, { "id": "f", "categories": [] } ] } ] } ] } , { "id": "2", "categories": [ { "id": "i", "categories": [] }, { "id": "j", "categories": [ { "id": "k", "categories": [] }, { "id": "l", "categories": [] } ] } ] } ] } }');
function print_hierarchy_by_child_id($json,$childId){
$result = array();
foreach($json->categories as $category){
if ($category->id==$childId){
// the entry-point was found
$result[] = $category->id;
return $result;
}
else{
$foundChildCat = print_hierarchy_by_child_id($category, $childId);
if (count($foundChildCat)){
// climb up to next parent if an entry-point was found
$result[] = $category->id;
$result = array_merge($result, $foundChildCat);
return $result;
}
}
}
return $result;
}
$firstExample = print_hierarchy_by_child_id($json->response, "c");
var_dump(implode(",",$firstExample)); // "1,b,c"
$secondExample = print_hierarchy_by_child_id($json->response, "i");
var_dump(implode(",",$secondExample)); // "2,i"
Поиск в глубину. Возвращает пустой массив, если путь не найден, в противном случае - массив идентификаторов в порядке последней глубины:
function path(string $search, array $nodes): array {
foreach ($nodes as $node) {
if ($node->id == $search) {
return [ $node->id ];
} else if (! empty($node->categories)) {
$path = array_merge([ $node->id ], path($search, $node->categories));
if (in_array($search, $path)) {
return $path;
}
}
}
return [];
}
Применение:
$find = 'f';
$json = json_decode(file_get_contents('data.json'));
$path = path($find, $json->response->categories);
echo implode(',', $path); // outputs 1,b,d,f
Скорее всего не оптимальная реализация. Если ваши данные JSON огромны, рассмотрите возможность перехода от рекурсии к итерации. Если он по-прежнему неэффективен (или просто занимает слишком много оперативной памяти), рассмотрите возможность использования Парсер потоковой передачи JSON.
Любая попытка? Петля?