rspec/rules/S6600/php/rule.adoc
2023-09-12 15:21:04 +02:00

66 lines
2.3 KiB
Plaintext

In PHP, incorrect use of parentheses can cause unexpected behavior in code.
Therefore, it is important to avoid the unnecessary usage of parentheses for language constructs.
== Why is this an issue?
Using constructs with parentheses can be misleading as it will produce a syntax that looks like a normal function call.
However those constructs have lower precedence in the evaluation order than some others operators, this can lead to a behavior completely different from what the function syntax would hint.
Also, some of the constructs have optional parameters, while modifying the code we may remove a parameter while keeping the parentheses, resulting in invalid code.
== How to fix it
When not necessary, do not use parentheses for the constructs.
To be noted that some construct such as `isset()`, `exit()` or `array()` does require them.
Here is the list of constructs for which parentheses could be used but should be avoided :
`return`, `echo`, `break`, `clone`, `case`, `continue`, `include`, `include_once`, `require`, `require_once`, `print`, `return`, `throw`, `yield`, `yield from`
=== Code examples
==== Noncompliant code example
[source,php,diff-id=1,diff-type=noncompliant]
----
echo("Hello World");
return(1);
include("file.php");
----
[source,php]
----
// Extra examples which show misleadings function syntax
// outputs "string" and "true"
// the expression ("string") && false is first evaluated to false, this is coerced to the empty string "" and printed
// the print construct returns 1 which is truthy, so code in the if block is run
if ( print("string") && false ) {
print "true";
}
// parse error
return();
// parse error: 'echo' construct accepts multiple parameters, but with parentheses this is an invalid syntax
echo("Hello", "World");
// this does not include the file 'vars.php' because 'include' construct has lower precedence than the comparison
// first, ('vars.php') == TRUE is being evaluated and is resolved into '1'
// then, the include construct will be executed with this value
// this is equivalent to: include('1')
if (include('vars.php') == TRUE) {
echo 'OK';
}
----
==== Compliant solution
[source,php,diff-id=1,diff-type=compliant]
----
echo "Hello World";
return 1;
include "file.php";
----
== Resources
=== Documentation
* https://www.php.net/manual/en/reserved.keywords.php[PHP List of Keywords]