PHP: Finding all instances of “Optional parameter declared before required parameter”
Among the many backward incompatible changes in PHP 8.1 is this one:
Optional parameters specified before required parameters
An optional parameter specified before required parameters is now always treated as required, even when called using named arguments. As of PHP 8.0.0, but prior to PHP 8.1.0, the below emits a deprecation notice on the definition, but runs successfully when called. As of PHP 8.1.0, an error of class ArgumentCountError is thrown, as it would be when called with positional arguments.
So how do you refactor your code and find all instances where you have functions doing this?
Here is a regex (regular expression) based approach:
ag -G php “function\s+[a-zA-Z0-9]+\s*\([^)]+=” | egrep ’=[^{]+,[^=]+(,|\))’
What does this do?
ag -G php
ag is a search utility like grep or ripgrep that makes it easy to search code. With this option we are asking ag to search PHP files.
“function\s+[a-zA-Z0-9]+\s*\([^)]+="
This regex is looking for any function declarations that have default values. So it’s looking for the string “function”, followed by one or more spaces, followed by an alphanumeric string (the function name), followed by zero or more spaces, followed by an opening paren “(”, followed by anything other than a closing paren “)”, followed by an equal sign.
egrep ’=[^{]+,[^=]+(,|\))’
Having identified the functions that use default values for arguments, let’s now find ones where a required argument is declared after an optional argument. This regex looks for an equal sign followed by two commas (that presumably separate function arguments) where there isn’t an equal sign between the two commas. In case there aren’t two commas, we look for closing paren because it could be the last argument in the function declaration.
Happy refactoring!