Bracketless instructions

PHP control structures, such as foreach, for, while, if/then/else,… are followed by one or several instructions. When there are several instructions, a block needs to be set up, with curly braces. When the following instruction is unique, it is possible to skip the brackets, and only use the instruction.

<?php

// multiple instructions in a for loop
$total = 0;
$squares = 0;
for($i = 0; $i < 10; ++$i) {
    $total += $i;
    $squares += $i ** 2;
}

// signle instructions in a for loop
$cubes = 0;
for($i = 0; $i < 10; ++$i) 
    $squares += $i ** 3;

?>

This feature has always been widely discussed among developers. Sometimes, those extra brackets are too much and make the syntax heavier than needed. The rest of the time, they are a matter of consistency and future usage : whoever will update the single instruction into two, will have to add the brackets.

We ran some statistics on 2408 Open Source projects to see what is the current situation on that thorny problem. Here are the figures.

One instruction usage

Out of 2408 projects, 2238 were found with at least one suitable control instruction that could be with or without brackets. Basically, 170 projects had not a single one line loop or ifthen. That’s 7.1% : it is a marginal case.

General usage

Then, we counted the number of occurrences over the all projects. This means that each for, foreach, while, do…while and if/then was counted. If/then is counted twice, when both the then and else blocks have only one instruction.

In total, 2.5 millions occurences used the brackets (2571914), while 0.4 million used no bracket (432761). All in all, it is 14.4% that are unbracketed.

In general, the vast majority of PHP source code are using brackets, even with single instructions.

Per project usage

As a complement, another interesting insight is the coding convention per project. With little impact on PHP itself and more impact on the code writing, choosing to go with or without brackets often turns into a core team value. This pushes the convention toward all with or without brackets.

We broke down the previous general figure into the percentage per project : how often are single instructions using brackets inside each project. That way, we can see which projects are systematic with or without brackets, and how the balance is tilted toward one or the other. The precise figures where rounded to make significant groups, and smooth local variations.

 

A very large number of projects (2079) have less than 5% of un-bracketed single instructions. In fact, 1867 of them are totally clean of un-bracketed instructions.

On the other end of the spectrum, un-bracketed single instructions are used 95% or more in 145 projects (137 are 100%).

In-between are the undecided projects : they don’t have a coding convention about it or are not enforcing it strictly (they might be on the way). All together, they are as numerous as the 100% bracketless (145).

Per 1% repartition of bracketless instructions
Per 1% repartition of bracketless instructions. The graph is troncanted to 300 to show the lower levels.

Practice show a clean lean toward always using brackets with every instruction. Undecided projects and never-bracketing ones are a minority.

Practice of the bracketless single instruction

There are tools to add or remove the brackets : PHP cs fixer and exakat, to name some of them. They may be added to CI pipeline, and enforce coding convention.

At the human level, some coding conventions, such as joomla (see Control Structures (General Code)), WordPress or PSR-12, are explicitely requesting it. They may also have quite some success having it applied, as this report from PHP CodeSniffer suggest : Control structure defined inline

PHP 9 could set this discussion aside

It seems that the PHP community is now well past the point in discussing this feature. It might be a good thing to move it directly into the language, and have PHP directly enforce such a feature.

Bracketless single instructions are rare enough to be a mere distraction. Even if they were more common, they lead to pointless discussions.

Backward incompatiblity is definitely a concern here, as some projects might have to update their code to be compatible. Although, this mass update is both very safe, with only local modifications, and there are tools ready to do it in a short amount of time.

A suggestion, for PHP 8.3 feature list, is this RFC : deprecate the single expression without brackets, for for(), foreach(), while(), do…while(). They would then join switch(), match(), functions and closures, classes and interfaces, etc. And drop it entirely in PHP 9.