PHP 8.0 : Named Parameters
17, April 2021

PHP is very popular for it's function naming and parameter orders. I've been working on PHP for more than 7 years and I still can't remember if $needle is the first parameter in strpos() or array_search() . Also I always mixup if $callback is the second parameter on array_map() and array_filter().

At last, PHP 8.0 introduces a way to battle with these inconsistency. Let's discuss about named parameters.


Named parameter is a way to pass parameter to a function by its name.

For example:

array_search() has below signature

array_search ( mixed $needle , array $haystack , bool $strict = false ) : int|string|false

So, array_search accepts three parameter. Currently, when calling this function the parameter names do not matter, we pass them by the order they are defined.

<?php
$arr = [1, 2, 3];

return array_search(2, $arr);

as $needle is defined as first parameter, we are bound to pass it at first. passing 2 as second parameter would result into error.


But, with named parameter, we can pass them by their name, ignoring their order.

<?php
$arr = [1, 2, 3];

return array_search(haystack: $arr, needle: 2);

Notice how we are passing $arr at first by its name haystack. It will work just like before even though we've switched the parameters.

So we don't need to remember parameter positions anymore. Both strpos and array_search can work in similar way:

<?php

array_search(haystack: [5, 6, 7], needle: 5);

strpos(haystack: "this is main string", needle: "str");


Another nice benefit of named parameter is, being able to skip optional parameters.

Optional parameter works just fine with named parameter.

<?php

function htmlspecialchars(string $string, int $flags = ENT_COMPAT , string|null $encoding = null , bool $double_encode = true ) : string
{
   // do something
}

Now, lets say we want to call this function but change $double_encode value, while keeping the other optional parameters to their default values:

// without named parameters
htmlspecialchars("html string", ENT_COMPAT, null, false);
// very long and boring. Not readable. Can't remember what "false" is for here.

// now, named parameters
htmlspecialchars(string: "html string", double_encode: false);
// isn't this nice? easily readable and we definitely know what "false" is doing here

// we can pass double_encode at first too
htmlspecialchars(double_encode: false, string: "html string");

Above, we didn't need to defined other optional variables (flags & encoding) because they will be assigned to their default value. We don't need to pass then while calling the function. We can just skip them.


Can we mix named parameters with regular ones?

Sure. While calling the same function, we can pass both regular and named parameters.

htmlspecialchars(
    "this is html string", // here we are passing parameter in regular way
    double_encode: false, // here we are passing named parameter
);

But remember, regular parameter should always be at first before named parameter. Otherwise it will throw error.

// this won't work
htmlspecialchars(
    double_encode: false,
    "this is html string",
);
// Fatal error: Cannot use positional argument after named argument


Note: You can't pass parameter by invalid name. It'll throw error.


Using Argument unpack operator

We can use argument unpack operator (...) to pass an array of arguments to a function/method.

  • If array keys are numeric then keys are ignored and values are treated as normal positional arguments.
  • If array keys are strings, key names are unpacked as a named argument.
  • Other key types will be TypeError.
function subtract($a, $b) {
    return $a - $b;
}

$arr = [5, 3]; // int keys
echo subtract(...$arr); // 2

$arr = ['b' => 3, 'a' => 5]; // string keys
echo subtract(...$arr); // 2


But, there is a reason why I don't use named parameters in my code.

Named parameters make parameter variable name so important that changing function argument name breaks API compatibility.

For example, lets say in my library, I've this function:

function add_money($wallet, $money){
    // something
}

and you, as a user of my library, call this function with named parameters:

add_money(
    wallet: $wallet, 
    money: $money
);


after some time , for some reason, I decide to change the parameter name to something different, like

function add_money($account, $amount){
    // something
}

But if I change it, your code won't work anymore because parameter names have been changed.


Many Library developers don't like this. In their opinion, parameter name should not be part of API.


But, other than that, named parameter truly is a great addition to PHP.


RFC: https://wiki.php.net/rfc/named_params


Write comment about this article: