[php] Using Default Arguments in a Function

I am confused about default values for PHP functions. Say I have a function like this:

function foo($blah, $x = "some value", $y = "some other value") {
    // code here!
}

What if I want to use the default argument for $x and set a different argument for $y?

I have been experimenting with different ways and I am just getting more confused. For example, I tried these two:

foo("blah", null, "test");
foo("blah", "", "test");

But both of those do not result in a proper default argument for $x. I have also tried to set it by variable name.

foo("blah", $x, $y = "test");   

I fully expected something like this to work. But it doesn't work as I expected at all. It seems like no matter what I do, I am going to have to end up typing in the default arguments anyway, every time I invoke the function. And I must be missing something obvious.

This question is related to php arguments default

The answer is


Optional arguments only work at the end of a function call. There is no way to specify a value for $y in your function without also specifying $x. Some languages support this via named parameters (VB/C# for example), but not PHP.

You can emulate this if you use an associative array for parameters instead of arguments -- i.e.

function foo(array $args = array()) {
    $x = !isset($args['x']) ? 'default x value' : $args['x'];
    $y = !isset($args['y']) ? 'default y value' : $args['y'];

    ...
}

Then call the function like so:

foo(array('y' => 'my value'));

This is case, when object are better - because you can set up your object to hold x and y , set up defaults etc.

Approach with array is near to create object ( In fact, object is bunch of parameters and functions which will work over object, and function taking array will work over some bunch ov parameters )

Cerainly you can always do some tricks to set null or something like this as default


function image(array $img)
{
    $defaults = array(
        'src'    => 'cow.png',
        'alt'    => 'milk factory',
        'height' => 100,
        'width'  => 50
    );

    $img = array_merge($defaults, $img);
    /* ... */
}

Pass an array to the function, instead of individual parameters and use null coalescing operator (PHP 7+).

Below, I'm passing an array with 2 items. Inside the function, I'm checking if value for item1 is set, if not assigned default vault.

$args = ['item2' => 'item2',
        'item3' => 'value3'];

    function function_name ($args) {
        isset($args['item1']) ? $args['item1'] : 'default value';
    }

<?php
function info($name="George",$age=18) {
echo "$name is $age years old.<br>";
}
info();     // prints default values(number of values = 2)
info("Nick");   // changes first default argument from George to Nick
info("Mark",17);    // changes both default arguments' values

?>

In PHP 8 we can use named arguments for this problem.

So we could solve the problem described by the original poster of this question:

What if I want to use the default argument for $x and set a different argument for $y?

With:

foo(blah: "blah", y: "test");

Reference: https://wiki.php.net/rfc/named_params (in particular the "Skipping defaults" section)


You can't do this directly, but a little code fiddling makes it possible to emulate.

function foo($blah, $x = false, $y = false) {
  if (!$x) $x = "some value";
  if (!$y) $y = "some other value";

  // code
}

It is actually possible:

foo( 'blah', (new ReflectionFunction('foo'))->getParameters()[1]->getDefaultValue(), 'test');

Whether you would want to do so is another story :)


UPDATE:

The reasons to avoid this solution are:

  • it is (arguably) ugly
  • it has an obvious overhead.
  • as the other answers proof, there are alternatives

But it can actually be useful in situations where:

  • you don't want/can't change the original function.

  • you could change the function but:

    • using null (or equivalent) is not an option (see DiegoDD's comment)
    • you don't want to go either with an associative or with func_num_args()
    • your life depends on saving a couple of LOCs

About the performance, a very simple test shows that using the Reflection API to get the default parameters makes the function call 25 times slower, while it still takes less than one microsecond. You should know if you can to live with that.

Of course, if you mean to use it in a loop, you should get the default value beforehand.


The only way I know of doing it is by omitting the parameter. The only way to omit the parameter is to rearrange the parameter list so that the one you want to omit is after the parameters that you HAVE to set. For example:

function foo($blah, $y = "some other value", $x = "some value")

Then you can call foo like:

foo("blah", "test");

This will result in:

$blah = "blah";
$y = "test";
$x = "some value";

You can also check if you have an empty string as argument so you can call like:

foo('blah', "", 'non-default y value', null);

Below the function:

function foo($blah, $x = null, $y = null, $z = null) {
    if (null === $x || "" === $x) {
        $x = "some value";
    }

    if (null === $y || "" === $y) {
        $y = "some other value";
    }

    if (null === $z || "" === $z) {
        $z = "some other value";
    }

    code here!

}

It doesn't matter if you fill null or "", you will still get the same result.


My 2 cents with null coalescing operator ?? (since PHP 7)

function foo($blah, $x = null, $y = null) {
    $varX = $x ?? 'Default value X';
    $varY = $y ?? 'Default value Y';
    // ...
}

You can check more examples on my repl.it


I recently had this problem and found this question and answers. While the above questions work, the problem is that they don't show the default values to IDEs that support it (like PHPStorm).

enter image description here

if you use null you won't know what the value would be if you leave it blank.

The solution I prefer is to put the default value in the function definition also:

protected function baseItemQuery(BoolQuery $boolQuery, $limit=1000, $sort = [], $offset = 0, $remove_dead=true)
{
    if ($limit===null) $limit =1000;
    if ($sort===null) $sort = [];
    if ($offset===null) $offset = 0;
    ...

The only difference is that I need to make sure they are the same - but I think that's a small price to pay for the additional clarity.


Examples related to php

I am receiving warning in Facebook Application using PHP SDK Pass PDO prepared statement to variables Parse error: syntax error, unexpected [ Preg_match backtrack error Removing "http://" from a string How do I hide the PHP explode delimiter from submitted form results? Problems with installation of Google App Engine SDK for php in OS X Laravel 4 with Sentry 2 add user to a group on Registration php & mysql query not echoing in html with tags? How do I show a message in the foreach loop?

Examples related to arguments

docker build with --build-arg with multiple arguments ARG or ENV, which one to use in this case? How to have multiple conditions for one if statement in python Gradle task - pass arguments to Java application Angularjs - Pass argument to directive TypeError: method() takes 1 positional argument but 2 were given Best way to check function arguments? "Actual or formal argument lists differs in length" Python: Passing variables between functions Print multiple arguments in Python

Examples related to default

Why Is `Export Default Const` invalid? Default Values to Stored Procedure in Oracle How do I change the default index page in Apache? Angularjs Template Default Value if Binding Null / Undefined (With Filter) Google Chrome default opening position and size new DateTime() vs default(DateTime) Using an attribute of the current class instance as a default value for method's parameter How do I set the default schema for a user in MySQL In NetBeans how do I change the Default JDK? PHP sessions default timeout