2

Я работаю с строкой JSON. Я конвертирую его в ассоциативный массив, чтобы найти определенные значения и изменить эти значения, когда найден определенный ключ (['content']). Глубина массива всегда неизвестна и всегда будет меняться.Как я могу рекурсивно искать и заменять значения внутри многомерного массива PHP с неизвестной глубиной?

Вот эта функция, которую я написал. Он принимает массив как аргумент и передает его по ссылке, чтобы сама переменная была изменена, а не копия локально этой функции.

$json_array = json_decode($json_string, true); 

function replace_data(&$json_array, $data='REPLACE TEST') 
{ 
    foreach($json_array as $key => $value) { 
     if ($key == 'content' && !is_array($value)) { 
      $json_array[$key] = $data; 

     } else { 
      if (is_array($value)) { 
       replace_data($value, $data); 
      } 
     } 
    } 

} 


replace_data($json_array, "test test test"); 
var_dump($json_array); 

Что я ожидал, так это каждый раз, когда клавиша [ «содержание»] встречается в независимо от того, какой глубины, он заменяет с этим значением, указанным в аргументе $ данных.

Но, когда я var_dump($json_array) Эти значения не изменяются.

Что мне не хватает?

+2

нуждается больше ссылок. –

+0

Не уверен, что вы имеете в виду. На странице руководства PHP указано, что «достаточно только определений функций, чтобы правильно передать аргумент по ссылке». Где я могу добавить дополнительные ссылки? http://php.net/manual/en/language.references.pass.php – user658182

+0

Ссылки обычно усложняют код и лучше их избегают. – Timurib

ответ

2

С array_walk_recursive:

function replace_data($json_array, $data = 'REPLACE TEST') { 
    array_walk_recursive($json_array, function (&$value, $key) use ($data) { 
     if (!is_array($value) && $key === 'content') { 
      // $value passed by reference 
      $value = $data; 
     } 
    }); 
    return $json_array; 
} 

И без ссылок:

function replace_data($json_array, $data = 'REPLACE TEST') { 
    foreach ($json_array as $key => $value) { 
     if (is_array($value)) { 
      $json_array[$key] = replace_data($value, $data); 
     } elseif ($key === 'content') { 
      $json_array[$key] = $data; 
     } 
    } 
    return $json_array; 
} 
+0

Я согласен, что 'array_walk_recursive' идеально подходит для этого. –

1

Чтобы расширить мой комментарий, вам нужно еще одна ссылка здесь:

foreach($json_array as $key => &$value) { 

Таким образом, ссылка на исходное значение передается, когда вы делаете рекурсивный вызов, а не локальной копии, созданной с foreach петля.

От PHP manual entry for foreach:

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

Вы также увидите в руководстве, что он рекомендует отключить ссылку на $value после цикла. Несмотря на то, что это, вероятно, не вызовет никаких проблем, если вы не сделаете этого в своей функции, лучше всего привыкнуть всегда отбрасывать ссылки, созданные в foreach таких петлях. Это может привести к некоторым strange looking problems, если вы этого не сделаете.