2011-08-11 11 views
9

Mam funkcję php, która ma nieograniczoną liczbę argumentów, które otrzymuję od func_get_args(). Mam kilka operacji z argumentami (zmieniając ciąg lub robiąc coś) i chcę, żeby to było jak przekazywanie argumentów przez odniesienie. Czy to możliwe?jak przekazać nieograniczoną liczbę argumentów przez odniesienie w php

przykład:

$test = 'foo'; 
$test2 = 'bar'; 

function test(){ 
    $args = func_get_args(); 
    foreach($args as $arg) 
     $arg .= 'baz'; 
} 

test($test, $test2); 
+0

Możliwy duplikat [php: zmiennej długości listy argumentów przez odniesienie] (http://stackoverflow.com/questions/1925253/php-variable-length-argument-list-by-reference) –

Odpowiedz

4

Gorąco wątpliwości, że jest to możliwe, ale znam jeden sposób można dostać to, co chcesz:

function test(&$args) { 
    foreach ($args as $arg) { 
     $arg .= 'baz'; 
    } 
} 

test(array(&$test, &$test2)); 
+0

It wygląda na to, że wkrótce będziemy mogli to zrobić za pomocą nowego operatora '...' w PHP 5.6. –

1

to działa:

$test = 'foo'; 
$test2 = 'bar'; 

function test(){ 
    $backtrace = debug_backtrace(); 
    foreach($backtrace[0]['args'] as &$arg) 
     $arg .= 'baz'; 
} 

test(&$test, &$test2); 

jednak używa to przekazywania czasu połączenia przez odniesienie, które jest przestarzałe.

+0

Niedozwolone w ogóle w PHP 5.4+ –

12

Jak odpowiedział w PHP: variable-length argument list by reference?, nie ma sposobu, aby w PHP łączyć argumenty funkcji o zmiennej długości i przekazywane przez referencje. Zamiast tego, połączona odpowiedź używa hack of deklarując 100 &argx s, a następnie używając get_num_args(), aby dowiedzieć się, ile faktycznie były używane. Gratulacje, znalazłeś szczególnie trudny zakątek w PHP;)

0

Potrzebowałem również tej funkcjonalności, wymyśliłem rozwiązanie.

function sayhello($params) { 
    //params hold an unlimited amount of references 
} 

sayhello([&$one, &$two]); 

Wszystko zależy od php> = 5.4. Jeśli używasz < = 5.4, użyj składni array() zamiast [].

kocham [] Chciaż, znacznie lepiej :)

+1

Przekazujesz dokładnie jeden argument, który jest tablicą (i działał obok tej składni również w

0

Korzystanie z obiektów jest rozwiązaniem

class O { 
    public $v; 
    public function __construct(&$p){ 
     $this->v = &$p; 
    } 
} 

function append_baz_to_all(){ 
    foreach(func_get_args() as &$arg){ 
     $arg->v .= 'baz'; 
    } 
} 

function test1(){ 
    echo "test1\n"; 
    $a='A';$b='B';$c='C';$d='D';$e='E';$f='F';$g='G'; 
    echo("\$a=$a \$b=$b \$c=$c \$d=$d \$e=$e \$f=$f \$g=$g\n"); 
    append_baz_to_all(new O($a), new O($b)); 
    echo("\$a=$a \$b=$b \$c=$c \$d=$d \$e=$e \$f=$f \$g=$g\n\n"); 
} 

//shortcutting 
function o(&$v){return new O($v);} 

function test2(){ 
    echo "test2\n"; 
    $a='A';$b='B';$c='C';$d='D';$e='E';$f='F';$g='G'; 
    echo("\$a=$a \$b=$b \$c=$c \$d=$d \$e=$e \$f=$f \$g=$g\n"); 
    append_baz_to_all(o($c), o($d), o($e)); 
    echo("\$a=$a \$b=$b \$c=$c \$d=$d \$e=$e \$f=$f \$g=$g\n\n"); 
} 


test1(); 
test2(); 
7

Od PHP 5.6 można użyć variadic odniesienie:

function test(&...$args) { 
    foreach ($args as &$arg) { 
     $arg .= 'baz'; 
    } 
} 
+0

Bezbłędne i wsparcie 5,6, nie mogę bardziej uwielbiać tej odpowiedzi, dzięki za aktualizację! –

0
function byref_alias() 
{ 
//$argz=func_get_args(); //byval, not what you want 
$argz=debug_backtrace()[0]['args']; //byref hack 
$argz[0]++; works 
} 
+0

Należy pamiętać, że chociaż te argumenty są oparte na odwołaniach, nie modyfikują oryginalnego argumentu wysłanego do funkcji, ale będą wysyłane przez odwołanie. – AbiusX

0

Działa dobrze dla mnie, gdy robisz coś takiego jak przykład poniżej. Myślę, że kluczem jest ustawienie odniesienia w foreach.

$var1 = '%DIR%/test'; 

replaceParameters(
    $var1, 
    $var2, 
    $var3 
); 

function replaceParameters(&$variables) { 

    $variables = array_filter(func_get_args()); 

    $parameters = [ 
     '%DIR%' => __DIR__, 
     '%FILE%' => __FILE__, 
    ]; 

    foreach($variables as &$variable) { 
     $variable = str_replace(array_keys($parameters), array_values($parameters), $variable); 
    } 

}