私は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()
viaに値渡しされます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()
マジックの「バグ」である可能性があります。既存の問題または関連する問題についてバグ データベースを調べたところ、1 つ見つかりましたが、再度見つけることができませんでした。別のレポートを発行するか、既存のレポートの再開を要求することを検討しています。