Вот трюк для передачи переменных по ссылкам с помощью магического метода __call:
Я не знаю, как долго это будет работать или в версиях ведьмы PHP.
Я тестировал на php 5.3.2
Прежде всего, вы не можете передать переменную $ arguments по ссылке $ в определении функции __call. Потому что php падает с ошибкой.
Итак, сначала:
Вот код, который не делает, что вы хотите с указанными аргументами, но почти хорошо;)
class A { public $x = array(); }
class Teszt{
private function addElement( &$list ){
$list->x[] = 'new element';
return count($list->x);
}
public function __call($name,$arguments){
if (!preg_match('#^add([0-9]+)Element$#', $name, $matches) || $matches[1]<1){
trigger_error ("Function is not exists teszt::$name", E_USER_ERROR);
}
$ret = null;
for($i=0;$i<$matches[1];$i++){
$ret = call_user_func_array(array($this,'addElement'), $arguments);
}
return $ret;
}
}
$a = new A();
$a->x = array('old element','old element');
$t = new Teszt();
$cnt = $t->add5Element($a);
var_dump($a);
var_dump($cnt);
ВЫВОД:
PHP Warning: Parameter 1 to Teszt::addElement() expected to be a reference, value given in /home/gkovacs/callMagicWithReference.php on line 19
PHP Stack trace:
PHP 1. {main}() /home/gkovacs/callMagicWithReference.php:0
PHP 2. Teszt->add2Element() /home/gkovacs/callMagicWithReference.php:27
PHP 3. Teszt->__call() /home/gkovacs/callMagicWithReference.php:0
PHP 4. call_user_func_array() /home/gkovacs/callMagicWithReference.php:19
PHP Warning: Parameter 1 to Teszt::addElement() expected to be a reference, value given in /home/gkovacs/callMagicWithReference.php on line 19
PHP Stack trace:
PHP 1. {main}() /home/gkovacs/callMagicWithReference.php:0
PHP 2. Teszt->add2Element() /home/gkovacs/callMagicWithReference.php:27
PHP 3. Teszt->__call() /home/gkovacs/callMagicWithReference.php:0
PHP 4. call_user_func_array() /home/gkovacs/callMagicWithReference.php:19
object(A)#1 (1) {
["x"]=>
array(2) {
[0]=>
string(11) "old element"
[1]=>
string(11) "old element"
}
}
NULL
оооо ((((
После небольшого «HACK»:
class A { public $x = array(); }
class Teszt{
private function addElement( &$list ){
$list->x[] = 'new element';
return count($list->x);
}
public function __call($name,$arguments){
if (!preg_match('#^add([0-9]+)Element$#', $name, $matches) || $matches[1]<1){
trigger_error ("Function is not exists teszt::$name", E_USER_ERROR);
}
$ret = null;
//Look at my hand, because i will cheat
foreach($arguments as $k=>&$v){ }
//end of cheat
for($i=0;$i<$matches[1];$i++){
$ret = call_user_func_array(array($this,'addElement'), $arguments);
}
return $ret;
}
}
$a = new A();
$a->x = array('old element','old element');
$t = new Teszt();
$cnt = $t->add5Element($a);
var_dump($a);
var_dump($cnt);
Выход:
object(A)#1 (1) {
["x"]=>
array(4) {
[0]=>
string(11) "old element"
[1]=>
string(11) "old element"
[2]=>
string(11) "new element"
[3]=>
string(11) "new element"
}
}
int(4)
Как мы и хотели. Это работает только с объектами, но не с массивами.
Есть способ с массивом-s для вызова время прохождения по ссылке ...
вот так: (и конечно, вы можете использовать этот способ и с объектами)
$cnt = $t->add5Element(&$a);
В этом случае php генерирует уведомления ...
Самый простой способ переопределить функцию, если это возможно.
в моем коде: private functionaddElement ($ list), не определяйте как ссылку в списке параметров. И, как вы читали в предыдущем сообщении, оно будет работать, потому что объекты передаются по ссылке автоматически
Но иногда вы не можете переопределить функции из-за реализованных интерфейсов или по другим причинам ...