Я читал о SO и в других местах, однако я не могу найти ничего убедительного.
Есть ли способ эффективно переносить ссылки через этот стек вызовов, приводя к желаемой функциональности, как описано в примере ниже? Хотя пример не пытается решить эту проблему, он, безусловно, иллюстрирует проблему:
class TestClass{
// surely __call would result similarly
public static function __callStatic($function, $arguments){
return call_user_func_array($function, $arguments);
}
}
// note argument by reference
function testFunction(&$arg){
$arg .= 'bar';
}
$test = 'foo';
TestClass::testFunction($test);
// expecting: 'foobar'
// getting: 'foo' and a warning about the reference
echo $test;
Сосредоточение внимания только на call_user_func_array ( )
, мы можем определить, что ( по крайней мере с PHP 5.3.1 ) вы не можете неявно передавать аргументы по ссылке:
function testFunction(&$arg){
$arg .= 'bar';
}
$test = 'foo';
call_user_func_array('testFunction', array($test));
var_dump($test);
// string(3) "foo" and a warning about the non-reference parameter
Путем явной передачи элемента массива $ test
как ссылку, мы можем облегчить это:
call_user_func_array('testFunction', array(&$test));
var_dump($test);
// string(6) "foobar"
Когда мы представляем класс с __ callStatic ()
, явный параметр времени вызова по ссылке, кажется, выполняется, как я ожидал, но появляются предупреждения об устаревании (в моя IDE):
class TestClass{
public static function __callStatic($function, $arguments){
return call_user_func_array($function, $arguments);
}
}
function testFunction(&$arg){
$arg .= 'bar';
}
$test = 'foo';
TestClass::testFunction(&$test);
var_dump($test);
// string(6) "foobar"
Отсутствие ссылочного оператора в TestClass :: testFunction ()
приводит к тому, что $ test
передается по значению в __ callStatic ()
, и, конечно же, передается по значению как элемент массива в testFunction ()
через call_user_func_array ()
. Это приводит к предупреждению, поскольку testFunction ()
ожидает ссылки.
После взлома всплыли некоторые дополнительные детали. Определение __ callStatic ()
, если оно написано для возврата по ссылке ( общедоступная статическая функция & __ callStatic ()
), не имеет видимого эффекта. Кроме того, преобразовав элементы массива $ arguments
в __ callStatic ()
в качестве ссылок, мы увидим, что call_user_func_array ()
работает примерно так, как ожидалось:
class TestClass{
public static function __callStatic($function, $arguments){
foreach($arguments as &$arg){}
call_user_func_array($function, $arguments);
var_dump($arguments);
// array(1) {
// [0]=>
// &string(6) "foobar"
// }
}
}
function testFunction(&$arg){
$arg .= 'bar';
}
$test = 'foo';
TestClass::testFunction($test);
var_dump($test);
// string(3) "foo"
Эти результаты ожидаются, поскольку $ test
больше не передается по ссылке, изменение не передается обратно в область его действия. Однако это подтверждает, что call_user_func_array ()
на самом деле работает, как ожидалось, и что проблема определенно ограничена вызывающей магией.
При дальнейшем чтении выясняется, что это может быть «ошибка» в Обработка PHP пользовательских функций и магия __ call ()
/ __ callStatic ()
. Я просмотрел базу данных ошибок на предмет существующих или связанных проблем и нашел ее, но не смог найти ее снова. Я подумываю о выпуске другого отчета или повторном открытии существующего отчета.