2

This seems a basic question I know but I've not been able to find the answer.

Let's assume a basic function:

function basicFunction ( $var1, $var2 = 1, $var3 = 2, $var4 = 5 )
{
// Do some stuff
// Return
}

Now let's assume I want to call that function with the following variables:

$var1 = 0

$var2 = 1

$var3 = 2

$var4 = 3

I can do this:

$someResult = basicFunction( 0, 1, 2, 3 );

$var2 and $var3 are already set though, so how would I call the function without having to repeat the value for $var2 and $var3?

Dharman
  • 30,962
  • 25
  • 85
  • 135
user1400941
  • 63
  • 1
  • 1
  • 5

9 Answers9

4

PHP does not support overloading. Therefore, you cannot skip them in any way if you don't move them to the very right of the list of arguments.

A common solution is to set a default value of a different type than expected (i.e. NULL). The actual default value is then set within the function. This approach is not really clean and takes some extra lines of code, but if the situation requires it, you can go with this:

function basicFunction($var1, $var2 = NULL, $var3 = NULL, $var4 = NULL) {
    if ($var2 === NULL) {
        $var2 = 1;
    }

    // ...
Niko
  • 26,516
  • 9
  • 93
  • 110
1

I just wrote this function that lets you call a function by an associative array. I've only tested it on scalar types though, but it should work fine for functions which take in ints, floats, strings, and booleans. I wrote this quite fast and it can definitely be improved in more ways than one:

function call_user_func_assoc($function, $array){
    $matches = array();
    $result = array();
    $length = preg_match_all('/Parameter #(\d+) \[ <(required|optional)> \$(\w+)(?: = (.*))? ]/', new ReflectionFunction($function), $matches);

    for($i = 0; $i < $length; $i++){
        if(isset($array[$matches[3][$i]]))
            $result[$i] = $array[$matches[3][$i]];
        else if($matches[2][$i] == 'optional')
            $result[$i] = eval('return ' . $matches[4][$i] . ';');
        else
            throw new ErrorException('Missing required parameter: $' . $matches[3][$i]);         
    }

    call_user_func_array($function, $result);
}

You can use it like this:

function basicFunction($var1, $var2 = "default string", $var3 = 2, $var4 = 5){
    var_dump(func_get_args());
}

call_user_func_assoc('basicFunction', array('var1' => "Bob", 'var4' => 30));

Which outputs:

array(4) {
  [0]=>
  string(3) "Bob"
  [1]=>
  string(14) "default string"
  [2]=>
  int(2)
  [3]=>
  int(30)
}
Paul
  • 139,544
  • 27
  • 275
  • 264
1

It is possible with PHP 8 now, see this answer for details https://stackoverflow.com/a/64997399/519333


Old answer:

function my_function(
    $id,
    $start = 0,
    $limit = 10,
    $filter = false,
    $include_duplicates => false,
    $optimize_fetch => false,
    $cache = false
) {
    if (is_array($id)) extract($id, EXTR_IF_EXISTS);

    /* ... */
}

And then

my_function(array('id' => 1, 'cache' => true));

Source: http://www.marco.org/2008/11/11/faking-named-parameters-in-php

simPod
  • 11,498
  • 17
  • 86
  • 139
0

Unfortunately I don't think php works like that.
If you are changing $var4 you have to include $var2 and $var3 becuase they come before $var4 in the function declaration.

you could pass an array to the function with the default values and only change the $var4 value, or change the order as nickb suggested.

http://www.php.net/manual/en/functions.arguments.php#functions.arguments.default

Any way to specify optional parameter values in PHP?

Community
  • 1
  • 1
dm03514
  • 54,664
  • 18
  • 108
  • 145
0

You need to put $var2 and $var3 at the end of the parameter list

function basicFunction ( $var1, $var4 = 5, $var2 = 1, $var3 = 2)

Now you can call:

basicFunction( 0, 3);

Otherwise you will have to specify all of the parameters. When calling functions, you must specify all of the parameters from left to right. The only time you can omit parameters is:

  1. If the parameter you want to omit has a default value.
  2. All of the parameters to the right of the current parameter have default values.
nickb
  • 59,313
  • 13
  • 108
  • 143
0

Have you thought of passing the variables as an array in some way? In that case you only include the variables you need to update

function basicFunction ( $arrayvar ){
    $arrayvar['var1']...

Update: Also you might use the func_get_args()-function that works like the first feature here

Gustav
  • 1,361
  • 1
  • 12
  • 24
0

More pure code 4 you (working 100%, php>5.3), working with classes and functions.

  function call_user_func_assoc($function, $array){
    if ((is_string($function)) && (count(explode('::',$function))>1))
        $function = explode('::',$function);

    $func = ((is_array($function)) || (count($function)>1)) ? new ReflectionMethod($function[0], $function[1]) : new ReflectionFunction($function);

    foreach($func->getParameters() as $key => $param) {
        if (isset($array[$key]))
            $result[$key] = $array[$key];
        elseif(isset($array[$param->name]))
            $result[$key] = $array[$param->name];
        else
            $result[$key] = $param->getDefaultValue();
    }
    return call_user_func_array($function, $result);
}
xercool
  • 4,179
  • 6
  • 27
  • 33
-1

to skip the values try like this

     $someResult = basicFunction( 0, 0, 0, 3 ); 

or if u have the values set then

       // passing values stored in var2,var3

       $var1 = 1;
       $var2 = 2;

    $someResult = basicFunction( 0, $var1, $var2, 3 );
Rinzler
  • 2,139
  • 1
  • 27
  • 44
-1

As I mentioned by the comment above, you should always keep the optional variables on the right end, because php arguments evaluated from left to right. However, for this case you can do some trick to get rid of duplicate values as follows:

$var2 = 1, $var3 = 2, $var4 = 5;
function basicFunction($var1, $var2 = null, $var3 = null, $var4 = null) {
    if($var2 === null)
        $var2 = $GLOBALS["var2"];
    if($var3 === null)
        $var3 = $GLOBALS["var3"];
    if($var4 === null)
        $var4 = $GLOBALS["var4"];
}

However, you had better solve this situation by relocating you arguments cleverly.

mert
  • 1,942
  • 2
  • 23
  • 43