PHP8's Named arguments

Have you ever wondered what was the use of the sixth argument of a function while reading code you wrote 2 months ago? I think it happened to all of us at least once, no matter the language we use. Unless this language has named arguments or something similar.

In this series of post, I'll go over the new things we can find in the last version of PHP. Let's dive together into the eighth version of PHP, see what's new and how it could be useful for us.

Named arguments aren't huge news. As I said earlier, it's a functionality that was already existing in some other languages. They sometimes name it “labels” like in Swift, but it's quite similar all in all.

Even in the PHP world, named arguments aren't a big new thing. For several years, in the last few versions, JetBrains displays in PHPStorm the name of the arguments in front of the values we want to execute for a function. It's a big help in reading and understanding the code. Of course, it's just displaying, the signature of your function doesn't really change.

The specificities of PHP 8

The syntax offered by PHP for this new functionality is the following :

<?php

functionName(paramName: $value);

And this is without changing the declaration :

<?php

function functionName($paramName) { ... }

At first sight, it doesn't change much and can seem a bit useless. But named arguments offer a lot of flexibility, they simplify the code and make it easier to read too.

For example, you can now entirely ignore the optional arguments in your function calls. Especially when you only want to change the last optional argument.

<?php

function getValue($key, $obj = null, $depth = 0, $isCaseSensitive = true) { ... }

getValue("key", null, 0, false); // positioned arguments only
getValue(key: "key", isCaseSensitive: false);

As you precise the name of the argument you want to use, the interpreter knows what you're talking about. This way you don't have to follow the order of arguments declaration.

<?php

function getValue($key, $obj = null, $depth = 0, $isCaseSensitive = true) { ... }

getValue(depth: 3, key: "key", isCaseSensitive: false);

You can also mix positioned arguments (the classic way to do it) and the named arguments. You get to choose what works best for you.

<?php

function trim($text, $leftOnly = false, $rightOnly = false) { ... }

trim($text, false, true); // positioned arguments only
trim($text, rightOnly: true);

However, you must always use the positioned arguments before the named arguments. You can easily understand why : if you have already indicated arguments, how can the interpreter guess which argument we want to use based on its position?

<?php

trim(righOnly: true, $text) // Error

Of course, all these rules and new features apply to the constructors and class methods too. Let's see an example here:

<?php

class MyClass extends ParentClass {
    private string $title;
    private bool $isUnique;
    private bool $isVariadic;
    
    public function __construct(
        string $title,
        bool $isUnique = false,
        bool $isVariadic = false,
        string $desc = null,
    ) {
        parent::__construct($text);
        
        $this->title = $title;
        $this->isUnique = $isUnique;
        $this->isVariadic = $variadic;
    }
}

new MyClass(title: "Science for All", isVariadic: true);
// or
new MyClass("Science for Anyone", isUnique: true);

Now you know (almost) everything about named arguments. You know how to use them and how to avoid rookie mistakes.

I have used this feature in several other languages and I really think it's a useful one. It makes my code so much easier to read without giving it kilometer-long variable names like you would in Java.

It makes the code easier to read right away, but also when you go back to it a few months after writing it. You need less context to understand the code, so it makes for an easier maintenance too.

What's your opinion on this? Let me know in the comments or on social media.