15

I have php function that has an unlimited number of args which I am getting from func_get_args(). I have some operations with arguments (changing string or doing something) and I want this to be like a passing argument by reference. is it possible?

example:

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

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

test($test, $test2);
bzzb
  • 151
  • 1
  • 3

8 Answers8

20

Since PHP-5.6 you can use a variadic reference:

function test(&...$args) {
    foreach ($args as &$arg) {
        $arg .= 'baz';
    }
}
Markus Malkusch
  • 7,738
  • 2
  • 38
  • 67
11

As answered in PHP: variable-length argument list by reference?, there is no way in PHP to combine variable-length and pass by reference function arguments. Instead, the linked answer uses a hack of declaring 100 &argxs, then using get_num_args() to figure out how many were actually used. Congratulations, you found a particularly hard corner in PHP ;)

It also shows how to do it with PHP 5.6+ variadics.

hakre
  • 193,403
  • 52
  • 435
  • 836
David Souther
  • 8,125
  • 2
  • 36
  • 53
5

I highly doubt that's possible, but I do know one way you could get what you want:

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

test(array(&$test, &$test2));
cutsoy
  • 10,127
  • 4
  • 40
  • 57
1

Works fine for me when doing something like the example below. I think the key is setting the reference in the 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);
    }

}
Simon Sessingø
  • 335
  • 2
  • 10
1

This works:

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

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

test(&$test, &$test2);

However, this uses call-time pass by reference which is deprecated.

newacct
  • 119,665
  • 29
  • 163
  • 224
0

I needed this functionality as well, I came up with a solution.

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

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

This depends on php >= 5.4 though. If you're on <= 5.4, use array() syntax instead of [].

I love [] tho, much better :)

Petter Thowsen
  • 1,697
  • 1
  • 19
  • 24
0

Using objects is the solution

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();
Mestre San
  • 1,806
  • 15
  • 24
0
function byref_alias()
{
 //$argz=func_get_args(); //byval, not what you want
 $argz=debug_backtrace()[0]['args']; //byref hack
 $argz[0]++; works
}
AbiusX
  • 2,379
  • 20
  • 26
  • Remember that although these arguments are byreference, they do not modify the original argument sent to the function, but they will be sent byreference. – AbiusX Jan 15 '16 at 05:34