PHP: обновить глобальную ссылочную переменную внутри области функции

Я пытаюсь изменить глобальное значение, которое в данный момент является ссылкой на другое значение. Моя текущая реализация не работает:

$anna = array('Name' => "Anna");
$bella = array('Name' => "Bella");
$girl = &$anna;

function change(){
    global $girl, $bella;
    $girl = &$bella;
    // $girl['Name'] is now 'Bella'
    output_girl(); // This still outputs 'Anna'
}

function output_girl(){
    global $girl;
    echo $girl['Name'];
}

change();

// What do we want to see?
echo $anna['Name']; // Should still be 'Anna'
echo $bella['Name']; // Should still be 'Bella'
echo $girl['Name']; // Should now be 'Bella' (in above example this will still be 'Anna')

Важные примечания:

  • Обходной путь с возвращаемым значением типа $girl = &change(); не является решением моей проблемы. Важно, чтобы глобальный $girl был изменен до завершения функции change(). (Причина в том, что это проблема внутри сложного проекта с вызовами вложенных функций, которые хотят использовать одни и те же глобальные переменные.)
  • Я знаю, что обходной путь может быть закодирован с использованием массива $GLOBALS. Однако меня особенно интересует, можно ли решить эту проблему с помощью ключевого слова global, как показано в примере кода. А если нет, узнать, почему это невозможно в PHP.
  • Удаление &чтобы сделать это $girl = $bella тоже не решение. Глобальный объект $girl всегда должен быть ссылкой на исходные массивы, определенные в начале скрипта. Мы никогда не сможем делать копии/разрушать ссылки.

Вопрос: невозможно ли это в PHP, когда я использую ключевое слово global? Если да, может ли кто-нибудь объяснить, почему? Если нет, может ли кто-нибудь объяснить, как заставить это работать?

🤔 А знаете ли вы, что...
PHP обеспечивает безопасность с помощью механизмов фильтрации ввода.


2
76
2

Ответы:

Решено

В PHP это невозможно сделать, используя только ключевое слово global.

Это потому, что references в php — это не то же самое, что pointers, как мы их знаем, например, из C/C++.

Когда вы выполняете $girl = &$anna; в строке 3, адрес переменной $anna не сохраняется в переменной $girl. Скорее, новый символ $girl создается для ссылки на ту же переменную, что и символ $anna.

Когда вы делаете global $girl, $bella; внутри функции. Создаются новые локальные символы $girl и $bella, которые ссылаются на свой глобальный аналог.

Когда вы делаете $girl = &$bella; внутри функции, локальный символ $girl заменяется на ссылку на ту же переменную, что и локальный символ $bella, но глобальный символ $girl не изменяется. После этого оба локальных символа $girl и $bella ссылаются на один и тот же глобальный символ $bella.


Проблема в том, что ваша глобальная переменная все еще ссылается на $anna.

вы можете проверить это, добавив print_r($GLOBALS['girl']):

function change(){
    global $girl, $bella;
    $girl = &$bella;
    print_r($girl); //referencing to bella
    print_r($GLOBALS['girl']); //referencing to Anna
    output_girl(); // This still outputs 'Anna'
}

}

Я не знаю правильного решения этой проблемы, но есть способ обойти эту проблему. Просто добавьте:

function change(){
    global $girl, $bella;
    $GLOBALS['girl'] = &$bella;
    output_girl(); // now is 'Bella'
}