PHP: проверьте, является ли объект/массив ссылкой

Извините, что спросили, его последнее, и я не могу изобразить способ сделать это... кто-либо может помочь?

$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]);
}

Главная цель состоит в том, чтобы скопировать массив БЕЗ любых ссылок.

Это возможно?

Спасибо.

15
задан lepe 30 June 2010 в 09:51
поделиться

3 ответа

Вы можете проверить ссылки в многомерном массиве, сделав копию массива, а затем изменяя и проверяя каждую запись по очереди:

$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'] .

7
ответ дан 1 December 2019 в 04:46
поделиться

Лучшее, что я могу сделать, это проверка двух переменных, чтобы определить, является ли одна ссылка на другую:

$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 всегда делает его ссылкой

3
ответ дан 1 December 2019 в 04:46
поделиться

может быть что-то рекурсивное.

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;
}
1
ответ дан 1 December 2019 в 04:46
поделиться
Другие вопросы по тегам:

Похожие вопросы: