37
Deprecated: Required parameter $xxx follows optional parameter $yyy in...

Since upgrading to PHP 8.0 this error is thrown when running code like this:

function test_function(int $var1 = 2, int $var2) {
    return $var1 / $var2;
}

This has worked in past versions of PHP without issue.

miken32
  • 42,008
  • 16
  • 111
  • 154
  • 3
    Change the order of the parameters, placing $xxx ahead of the optional parameter $yyy. – Darren Murphy Apr 27 '21 at 12:06
  • There is an answer to the question already. Doing what you suggest would mean rewriting every use of your function across your code base. – miken32 Apr 27 '21 at 13:30
  • for a quick solution, use `function test_function(int $var1 = 2, int $var2=0)`, since where ever you are using the function, it is passing a value for `$var2`. then in spare time, search and update your code. – bluepinto Jun 22 '23 at 05:30

5 Answers5

55

This style of function declaration has been deprecated in PHP 8.0. Writing functions like this has never made sense, since all parameters (up to the last required one) would need to be specified when the function was called. It also caused confusion with use of the ReflectionFunctionAbstract class to analyze functions and methods.

The new deprecation simply ensures that function signatures follow the common sense assumption that required parameters, which must appear, should always be declared before optional ones.

The function should be rewritten to remove the default value on the earlier parameters. Since the function could never be called without declaring all parameters, this should have no effect on its functionality.

function test_function(int $var1, int $var2) {
    return $var1 / $var2;
}
miken32
  • 42,008
  • 16
  • 111
  • 154
  • 5
    "since all parameters (up to the last required one) would need to be specified when the function was called" . I disagree https://3v4l.org/Nb6i6 ;) – Rain Dec 14 '20 at 22:43
  • 3
    Very impressive nitpicking! – miken32 Dec 14 '20 at 22:46
  • 7
    "Writing functions like this has never made sense" - I disagree. There are often occasions where arguments may be ordered differently for sanity or readability reasons. This deprecation seems like an unnecessary and annoying change. – Enverex Apr 08 '21 at 13:14
  • 3
    @Enverex the default value specified in such a case could never be used, so it serves no purpose. I've been programming professionally in PHP for more than 15 years and I've never needed to do it. Argument order and default values are not intended for use as documentation, that's what PHPDoc is for. – miken32 Apr 08 '21 at 16:17
  • "the default value specified in such a case could never be used" Yes it could, you pass null for values you wish to use the default. Also I'm not talking documentation here, just friendlier argument ordering. – Enverex Apr 09 '21 at 10:41
  • 1
    @Enverex If you pass `null` you get `null` for the parameter, not the default value. https://3v4l.org/MGWIR – miken32 Apr 09 '21 at 15:20
  • 1
    @Rain what php8 feature is your example using? Assuming it must be a new php8 feature since its a syntax error in the previous versions. – chiliNUT May 11 '21 at 07:38
  • 1
    @chiliNUT Named Arguments. – Rain May 11 '21 at 08:42
  • 6
    @Rain - I disagree too. My 2 cents... This PHP8 deprecation wasn't well thought out at all. In PHP8, they added named parameters which means that you can now call parameters in any order as long as you call them by name like this: `func(param1: "value1", param2: "value2")` So, that syntax compliments being able to specify default values for any parameter in any order. @miken32 - You said "since all parameters (up to the last required one) would need to be specified when the function was called" - This isn't true anymore – Ray Perea Jul 19 '21 at 03:52
11

The required parameter without a default value should come first.

function test_function(int $xxx, int $yyy = 2)
{
    return $xxx * $yyy;
}
 
Al Foиce ѫ
  • 4,195
  • 12
  • 39
  • 49
0

"If a parameter with a default value is followed by a required parameter, the default value has no effect."

This is deprecated as of PHP 8.0.0 and can generally be resolved

  1. by dropping the default value
  2. by changing the position of parameters as suggested above

, without a change in functionality.

This method worked in my case =)

I was facing the following error :

ErrorException Required parameter $id follows optional parameter $getLink

Following code was generating this Exception

public function fo($getLink = null , $id)
{ ......
}

To Solve this error, I Changed the position of the parameters as suggested in the following code :

 public function fo($id, getLink = null)
    { ......
    }

Done =)

Omkar Ghurye
  • 195
  • 1
  • 8
  • Every place you use that method you would need to change your code. Why would you do this instead of just setting a default on the second parameter? – miken32 Feb 20 '22 at 17:23
  • @miken32 "If a parameter with a default value is followed by a required parameter, the default value has no effect." This is deprecated as of PHP 8.0.0 and can generally be resolved by dropping the default value or by changing the position of parameters as suggested above, without a change in functionality. – Omkar Ghurye Feb 23 '22 at 12:01
  • 1
    It completely changes the function; now you have to find and rewrite every single line of code that uses this function. My question was, why is this better than just dropping the default value, which involves no changes to other code? Not to mention this subpar approach has already been given in another answer. – miken32 Feb 23 '22 at 14:02
0

If anybody is trying to find a way of spotting functions that need updating, you can use this regular expression in linux via grep which will output the results to a file called results.txt. It will only search inside .php files.

Took me a while to get it to work and it probably needs more tweaking!

flag -i = Case insensitive search
flag -n = print line number match was found on with the file found
flag -r = recursive from current location downwards
flag -E = Use extended regular expression rules


grep -irnE --include \*.php 'function ([a-zA-Z0-9_]*?)[ ]?\(.*?\$[a-zA-Z0-9_]*?=.*?(\$[a-zA-Z0-9_]*?)[\),]{1}[^\{]*?' > results.txt

Hope this helps anyone trying to find and correct errors.

Watts Epherson
  • 692
  • 5
  • 9
  • Pretty sure ERE doesn’t support lazy matches so all the `*?` are redundant. And a few places it should be a `+` instead. But really an IDE will be the best tool for this. It will catch things like multi line signatures that grep can’t. – miken32 Mar 16 '23 at 13:50
  • 1
    You could probably also use PHP’s built-in token parser to do this, though it wouldn’t be a short solution! – miken32 Mar 16 '23 at 13:52
  • @miken32 - Tested it in linux with test scripts and matched everything I could come up with as combinations. Please do test it yourself directly though and confirm as guessing isn't advised. Might be different flavours possibly, no idea. I just know the above found what I needed it too but very happy to update it if need be so t's 100% perfect! - will check out the token parser thank you. – Watts Epherson Mar 16 '23 at 13:55
  • I'm not saying it won't work, just a) `.*?` is exactly the same as `.*` in ERE and b) your regex allows for empty/invalid arguments with things like `\$[a-zA-Z0-9_]*`. Also: a `{1}` quantifier is redundant, and a case-insensitive search means not having to check both a-z and A-Z. – miken32 Mar 16 '23 at 18:15
-1

the solution that worked fine for me was interchanging the position of the parameters ensuring no parameter comes after any parameter with the default value set to null.