Я читал об 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()
, если оно написано для возврата по ссылке (public static function &__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()
.Я просмотрел базу данных ошибок на предмет существующих или связанных проблем и нашел ее, но не смог найти ее снова.Я рассматриваю возможность выпуска другого отчета или запроса на повторное открытие существующего отчета.