phpargumentsdefaultvariadic-functionsnamed-parameters

How to skip default named arguments while setting a named variadic argument in a function call?


I have an existing method:

public function dbQuery(
    string $query,
    bool $flag1 = false,
    int $flag2 = SOME_DEFAULT,
    bool $flag3 = false
)

Now I want to adapt it so it is possible to pass in binding values as variadic arguments, but without breaking the current interface (I know arg flags are an anti-pattern), to be:

public function dbQuery(
    string $query,
    bool $flag1 = false,
    int $flag2 = SOME_DEFAULT,
    bool $flag3 = false,
    mixed ...$params
)

How can I then call dbQuery while keeping the default flags while passing in params?

I've tried:

Nothing with quite this usage is shown in: https://wiki.php.net/rfc/variadics or https://wiki.php.net/rfc/named_params

Although in the later RFC it explictly shows that default named arguments before variadics is a valid signature, but not how to access the variadics.


Solution

  • A comment on this related question leads me to an interesting workaround, with caveats: you can populate named entries in the variadic argument by using names that don't match parameters in the signature.

    This works because the named parameters RFC specified:

    Functions declared as variadic using the ...$args syntax will also collect unknown named arguments into $args.

    So in your example, this would be a valid call:

    $whatever->dbQuery('my query', params1: 1, param2: 2, param3: 3);
    

    Which would result in var_dump($params) looking like this:

    array(3) {
      ["params1"]=>
      int(1)
      ["param2"]=>
      int(2)
      ["param3"]=>
      int(3)
    }
    

    Live demo

    You could then use array_values or loop over the array ignoring keys if you wanted a positional array.