The Required, The Optional, The Useless, and The Weird: of 
In PHP, parentheses ()
aren’t just punctuation : they play different roles depending on where and how they’re used. Some are compulsory, others are optional, and a few are just useless clutter. And then, there’s the weird one: (cast). Let’s review all PHP parentheses usages down.
Compulsory Parentheses
The compulsory parentheses are the ones PHP needs to make sense of the code. No one can omit them, and the source won’t even compile without them, so they are compulsory.
Function definitions and method calls
And vice-versa, obviously.
<?php $double = fn($x) => $x * 2; // Parameters require parentheses (unless none) echo $double('hello'); // With Arguments ?>
Control structures like if, while, switch, match
Baked into the PHP parser, nothing much to add there.
<?php if ($a > $b) { echo match($b) { 1 => 'C', default => 3 }; } ?>
Optional Parentheses
Sometimes, parentheses are allowed but not necessary, so it is up to the human in the room to decide if it makes the code clearer, or valid.
Grouping expressions
This often applies to math expression, and more generally, operators. One may even wonder, if operators evolved into functions, they probably brought the parentheses with them.
<?php $result = ($a + $b) * $c; // Required for proper precedence $result = $a * $c + $b * $c; // The above may be removed $result = ($you + $me) + $elephpants; // Required for clearer reading ?>
Such parentheses are optional, as the expression may be refactored without them. Not that it would help in anything, it’s just possible.
Operator precedence
Some expressions are not the same, with and without parentheses, thanks to operators precedence. Both are valid, and one is definitely more popular, and in the end, it is a choice.
<?php // $c is a boolean while ($c = foo() === 3) {} // $c is an integer while (($c = foo()) === 3) {} // $c is an integer while (3 === $c = foo()) {} ?>
Inverting the operators helps to make this more obvious, if not more readable.
Readability
All expressions use the operators precedence rules, but they are hard to read: at least, for some of us. Then, adding parentheses makes it more readable.
<?php // if $x is not an instance of Foo if (!$x instanceof Foo) {} if (!($x instanceof Foo)) {} // if $source is null, spread range(1,4), or spread it $array = [...$source ?? range(1,4)]; $array = [...($source ?? range(1,4))]; ?>
The equal sign
Actually, one operator that often needs clarification with parentheses is the =
sign. An assignation has one of the lowest precedence among operators, and it never expands to the next expression, but rather only capture the next result.
<?php function foo() { return 4;} $d = 3 + $c = foo() + 5; // $d = 12, C = 4 $d = 3 * $c = foo() + 5; // $d = 17, C = 4 echo $d; ?>
Of course, it is also a confusing syntax from the beginning: just try to guess the execution order in such expressions.
Parentheses with new: inside
new
operator works with or without parentheses. When the constructor requires any argument, the parentheses are compulsory.
When the constructor requires no arguments, then the parentheses become optional. They are usually recommended, as a common best practise.
<?php class W { function __construct($a) {} } $c = new W(1); $a = new X; // valid $b = new X(); // prefered class X {} $a = new X; // valid $b = new X(); // prefered ?>
Parentheses with new: outside
new
operator produces a new object. Sometimes, that object needs to be accessed immediately, for a method call, or a property read. At that point, the parentheses used to be compulsory.
When the constructor requires no arguments, then the parentheses become optional. They are usually recommended, as a common best practise.
Since PHP 8.4, it is possible to use the newly created object immediately, without parentheses. Or, to be precise, only with the constructor parentheses (see section just before).
<?php class W { public $property = 'a'; } // before PHP 8.4 echo (new W)->property; // after PHP 8.4 echo new W()->property; ?>
Useless Parentheses
There are places where parentheses are thought to be useful, but they are not. This is the case with all PHP language constructs, such as echo
, print
, include
, etc.
<?php echo('Hello'); // Works echo 'Hello'; // Also works ?>
Here, the parentheses are accepted, like any other expression, as the single argument for the language construct. Parentheses forces the inner expression to be resolved, and passes the results to the outer expression.
First, this means that nesting parenthesis is completely arbitrary, and futile.
<php echo((((((((('Hello')))))))))); // Works, but don't do it ?>
Secondly, it hides the fact that echo
accepts multiple arguments, separated with a comma. In fact, to make the one-argument echo
work, the strings must be concatenated first, to be useful.
<?php echo('Hello'. ' ' . 'World'); // Hello World echo 'Hello', ' ', 'World'; // Hello World ?>
echo
is the only one with that hidden feature. print
, include
only accept one argument, and empty
works only with parentheses.
The Weird Parentheses: casting, constants and functioncall
Finally, there is an odd bug in the parsing engine, that catches anything that resemble a cast, such as (float)
, (int)
… etc. in normal syntax.
<?php const int = 3; var_dump(int); // Parse error: syntax error, unexpected token "(int)" ?>
So, the recommendation here is to avoid using cast
names as global constants: int, float, array, string, void. Luckily, it is not a common behavior.
PHP parentheses usage
Parentheses are quite versatile in PHP, ranging from compulsory to down right useless or buggy. It is still a very convenient tool, in particular to manage priorities between operators. When in doubt, just use them.