Извините, что спросили, его последнее, и я не могу изобразить способ сделать это... кто-либо может помочь?
$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
);
шоу $room var_dump:
...
'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);
В данных из вашего примера $ room ['мебель']
и $ roomCopy ['мебель']
будут отдельными массивами (поскольку $ 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;
}