Извините, что попросил, его поздно, и я не могу понять, как это сделать … любой может помочь?
$users = array( array( "name" => "John", "age" => "20" ), array( "name" => "Betty", "age" => "22" ) ); $room = array( "furniture" => array("table","bed","chair"), "objects" => array("tv","radio","book","lamp"), "users" => &$users );
var_dump $ room показывает:
... 'users' => & ...
Это означает, что «пользователи» являются ссылкой.
Я хотел бы сделать что-то вроде этого:
foreach($room as $key => $val) { if(is_reference($val)) unset($room[$key]); }
Основная цель – скопировать массив без каких-либо ссылок.
Это возможно?
Спасибо.
Вы можете проверить ссылки в многомерном массиве, сделав копию массива, а затем изменив и протестировав каждую запись по очереди:
$roomCopy = $room; foreach ($room as $key => $val) { $roomCopy[$key]['_test'] = true; if (isset($room[$key]['_test'])) { // It's a reference unset($room[$key]); } } unset($roomCopy);
с$roomCopy = $room; foreach ($room as $key => $val) { $roomCopy[$key]['_test'] = true; if (isset($room[$key]['_test'])) { // It's a reference unset($room[$key]); } } unset($roomCopy);
С вашими данными примера $room['furniture']
и $roomCopy['furniture']
будут отдельными массивами (поскольку $roomCopy
– это копия $room
), поэтому добавление нового ключа к одному не повлияет на другое. Но $room['users']
и $roomCopy['users']
будут ссылаться на один и тот же массив $users
(так как это скопированная ссылка, а не массив), поэтому, когда мы добавляем ключ в $roomCopy['users']
это видно в $room['users']
.
Лучшее, что я могу сделать, это тест двух переменных, чтобы определить, является ли ссылка ссылкой на другую:
$x = "something"; $y = &$x; $z = "something else"; function testReference(&$xVal,&$yVal) { $temp = $xVal; $xVal = "I am a reference"; if ($yVal == "I am a reference") { echo "is reference<br />"; } else { echo "is not reference<br />"; } $xVal = $temp; } testReference($x,$y); testReference($y,$x); testReference($x,$z); testReference($z,$x); testReference($y,$z); testReference($z,$y);
но я сомневаюсь, что это очень помогает
Действительно грязный метод (не очень хорошо протестирован):
$x = "something"; $y = &$x; $z = "something else"; function isReference(&$xVal) { ob_start(); debug_zval_dump(&$xVal); $dump = ob_get_clean(); preg_match('/refcount\((\d*)\)/',$dump,$matches); if ($matches[1] > 4) { return true; } else { return false; } } var_dump(isReference($x)); var_dump(isReference($y)); var_dump(isReference($z));
Чтобы использовать этот последний метод в коде, вам нужно сделать что-то вроде:
foreach($room as $key => $val) { if(isReference($room[$key])) unset($room[$key]); }
потому что $ val никогда не является ссылкой, поскольку это копия исходного элемента массива; и использование & $ val всегда делает ссылку
возможно, что-то рекурсивное.
function removeReferences($inbound) { foreach($inbound as $key => $context) { if(is_array($context)) { $inbound[$key] = removeReferences($context) }elseif(is_object($context) && is_reference($context)) { unset($inbound[$key]); //Remove the entity from the array. } } return $inbound; }
сfunction removeReferences($inbound) { foreach($inbound as $key => $context) { if(is_array($context)) { $inbound[$key] = removeReferences($context) }elseif(is_object($context) && is_reference($context)) { unset($inbound[$key]); //Remove the entity from the array. } } return $inbound; }
function var_reference_count(&$xVal) { $ao = is_array($xVal)||is_object($xVal); if($ao) { $temp= $xVal; $xVal=array(); } ob_start(); debug_zval_dump(&$xVal); $dump = ob_get_clean(); if($ao) $xVal=$temp; preg_match('/refcount\((\d*)\)/',$dump,$matches); return $matches[1] - 3; } //-------------------------------------------------------------------------------------------
Это работает с объектами и массивами HUDGE.
если вы хотите избавиться от рекурсивных элементов:
<?php $arr=(object)(NULL); $arr->a=3; $arr->b=&$arr; //$arr=array('a'=>3, 'b'=>&$arr); print_r($arr); $arr_clean=eval('return '.strtr(var_export($arr, true), array('stdClass::__set_state'=>'(object)')).';'); print_r($arr_clean); ?>
вывод:
stdClass Object ( [a] => 3 [b] => stdClass Object *RECURSION* ) stdClass Object ( [a] => 3 [b] => )