Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Best way to emulate Ruby "splat" operator in PHP function signatures [Method overloading]

In Ruby

def my_func(foo,bar,*zim)
  [foo, bar, zim].collect(&:inspect)
end

puts my_func(1,2,3,4,5)

# 1
# 2
# [3, 4, 5]

In PHP (5.3)

function my_func($foo, $bar, ... ){
  #...
}

What's the best way to to do this in PHP?

like image 509
maček Avatar asked Aug 25 '10 21:08

maček


2 Answers

Copying my answer from another question related to this:

This is now possible with PHP 5.6.x, using the ... operator (also known as splat operator in some languages):

Example:

function addDateIntervalsToDateTime( DateTime $dt, DateInterval ...$intervals )
{
    foreach ( $intervals as $interval ) {
        $dt->add( $interval );
    }
    return $dt;
}
like image 178
jonathancardoso Avatar answered Sep 25 '22 13:09

jonathancardoso


Try

  • func_get_args — Returns an array comprising a function's argument list

PHP Version of your Ruby Snippet

function my_func($foo, $bar)
{
    $arguments = func_get_args();
    return array(
        array_shift($arguments),
        array_shift($arguments),
        $arguments
    );
}
print_r( my_func(1,2,3,4,5,6) );

or just

function my_func($foo, $bar)
{
    return array($foo , $bar , array_slice(func_get_args(), 2));
}

gives

Array
(
    [0] => 1
    [1] => 2
    [2] => Array
        (
            [0] => 3
            [1] => 4
            [2] => 5
            [3] => 6
        )
)

Note that func_get_args() will return all arguments passed to a function, not just those not in the signature. Also note that any arguments you define in the signature are considered required and PHP will raise a Warning if they are not present.

If you only want to get the remaining arguments and determine that at runtime, you could use the ReflectionFunction API to read the number of arguments in the signature and array_slice the full list of arguments to contain only the additional ones, e.g.

function my_func($foo, $bar)
{
    $rf = new ReflectionFunction(__FUNCTION__);
    $splat = array_slice(func_get_args(), $rf->getNumberOfParameters());
    return array($foo, $bar, $splat);
}

Why anyone would want that over just using func_get_args() is beyond me, but it would work. More straightforward is accessing the arguments in any of these ways:

echo $foo;
echo func_get_arg(0); // same as $foo
$arguments = func_get_args();
echo $arguments[0]; // same as $foo too

If you need to document variable function arguments, PHPDoc suggest to use

/**
 * @param Mixed $foo Required
 * @param Mixed $bar Required
 * @param Mixed, ... Optional Unlimited variable number of arguments
 * @return Array
 */

Hope that helps.

like image 25
Gordon Avatar answered Sep 22 '22 13:09

Gordon