Недавно у меня возникла проблема (PHP: значение переменной загадочным образом установлено на 0 ), где переменная передавалась по значению в функцию PHP, и каким-то образом значение этой переменной было изменено, например:
$var = 'hello';
some_function($var);
echo $var; // outputs 0
Было высказано предположение, что это старая функция, написанная на C, и внутри она что-то делала, чтобы испортить переменную, поскольку в C, по-видимому, вы можете делать такие вещи. Во всяком случае, я попытался сначала скопировать значение, а затем передать его, например:
$var = 'hello';
$var2 = $var;
some_function($var2);
echo $var; // Still outputs 0
Конечно, это не помогло, потому что, когда я читал здесь PHP просто указывает $var2
в таблице символов на тот же контейнер zval, что и $var
, и увеличивает счетчик ссылок этого контейнера zval. Конечно, если $var2
переназначить "по значению", для него надо создать новый zval-контейнер, но это не было обычным назначением по значению, судя по всему (об этом немного было в предыдущем вопросе с магическим методом __set()
вещь). Я предположил, что что-то происходит с адресом физической памяти, по которому хранится значение, а не присваивание, происходящее через обычный механизм PHP, и, таким образом, все, что указывает на этот zval, будет затронуто. Очень хорошо.
Мой обходной путь состоял в том, чтобы найти способ клонировать примитив $var
. Извините, если это повторение, но я нашел массу материала о клонировании классов, но ничего о клонировании примитивов, я думаю, потому что PHP должен делать это правильно автоматически. В итоге я использовал это:
$var = 'hello';
$serialized_var = serialize($var);
$var2 = unserialize($serialized_var);
some_function($var2);
echo $var; // Outputs 'hello', yay!
Мне просто интересно, есть ли лучший способ? Давайте предположим, что нет другого обходного пути, например, использование другой функции или что-то в этом роде, и что мы должны получить настоящую копию переменной. Как можно было это сделать?