Почему PHP позволяет передавать литерал в параметр передачи по ссылке в одном случае, но не в других?

Функция array_shift() принимает один параметр по ссылке. Передача литерала массива приводит к фатальной ошибке:

$ php -r ‘var_export (array_shift (array («Test # 0»));’; echo

Неустранимая ошибка: только переменные могут быть переданы по ссылке в коде командной строки в строке 1

Это не так, как ожидалось. Тем не менее, PHP ведет себя странно, когда функция вызывается с call_user_func_array:

<?php
var_export(call_user_func_array("array_shift", array(array("Test #1"))));
echo "\n";

$arg1 = array("Test #2");
var_export(call_user_func_array("array_shift", array($arg1)));
echo "\n";

$args = array(array("Test #3"));
var_export(call_user_func_array("array_shift", $args));
echo "\n";

Когда выполнено:

$ php test.php

«Тест № 1»

Предупреждение: параметр от 1 до array_shift () должен быть ссылкой, значение указано в /Users/kcc/test.php в строке 6
НОЛЬ

Предупреждение: параметр от 1 до array_shift () должен быть ссылкой, значение указано в /Users/kcc/test.php в строке 10
НОЛЬ

Понятно что call_user_func_array() не вызовет фатальную ошибку, но почему первая форма работает нормально?

5

Решение

От call_user_func_array () документация:

До PHP 5.4 ссылочные переменные в param_arr передаются в функцию по ссылке, независимо от того, ожидает ли функция передачи соответствующего параметра по ссылке. Эта форма передачи времени вызова по ссылке не создает уведомления об устаревании, но, тем не менее, она устарела и была удалена в PHP 5.4. Кроме того, это не относится к внутренним функциям, для которых признается подпись функции. Передача по значению, когда функция ожидает параметр по ссылке, приводит к предупреждению и call_user_func() вернуть FALSE (есть, однако, исключение для переданных значений с числом ссылок = 1, например в литералах, поскольку они могут быть превращены в ссылки без вредных последствий — но также без записи в это значение, имеющее какой-либо эффект -; однако не полагайтесь на это поведение, так как счетчик ссылок является деталью реализации, а обоснованность такого поведения сомнительна).

(акцент мой)

Начиная с PHP 5.4, call_user_func_array() передает все свои аргументы по значению указанному $callback, за исключением случая, выделенного жирным шрифтом в приведенной выше ручной цитате.

В Test #1у вас есть чистый литерал, поэтому вы столкнулись со специальным исключением, описанным в документации: литерал можно превратить в ссылку без нежелательных побочных эффектов (потому что он будет просто отброшен, когда call_user_func_array() готово).

В Test #2 а также Test #3у вас нет чистого литерала, и потому что внутренне, array_shift определяется как получение его параметра по ссылке, call_user_func_array() поднимает предупреждение, описанное выше.

В PHP 7 Test #1 «исправлено» и теперь корректно выдает предупреждение.

3

Другие решения

Других решений пока нет …

По вопросам рекламы [email protected]