Parentheses On Echo

ID

php.parentheses_calls_echo

Severity

high

Remediation Complexity

trivial

Remediation Risk

low

Remediation Effort

low

Resource

Code Smell

Language

Php

Tags

code_smell, readability

Description

Reports echo(…​) written as though echo were a function.

The trigger is deliberately narrow: the whole of echo’s single argument must be one parenthesised group. That is the form that reads as a call, and the only form where dropping the parentheses is unconditionally safe. Parentheses that carry meaning are left alone — `echo (1 + 2) * 3; needs them to group the addition, echo (string) $v; is a cast, echo ($obj)→name(); parenthesises the receiver of a chain, and echo sprintf('%s', $v); is a real function call.

print is not covered, though it looks the same. Unlike echo it is a real expression that yields 1, so print($x) is not a false claim about the language, and its parentheses can be load-bearing: print binds looser than almost every operator, so removing them changes what gets printed.

Rationale

echo is a language construct, not a function. The parentheses parse — as an ordinary parenthesised expression around the single thing being printed — so the line works, and that is precisely what makes it misleading: it tells the reader something the language does not support.

Two things follow that a reader who believes it will get wrong. echo takes a comma-separated list of values, so echo "a", "b"; is valid while echo("a", "b"); is a parse error — and there is no way to read the second form as the call it resembles. And echo is a statement, so it has no value: it cannot be used where a function’s result would be expected, not in an expression, not as a callback, not with array_map. The parentheses invite exactly the edit that will not compile.

<?php
class InvoiceView
{
    public function render(array $invoice): void
    {
        echo("Invoice " . $invoice['id']);                  // FLAW
        echo ($invoice['total'] > 0 ? 'due' : 'settled');    // FLAW

        echo 'Invoice ' . $invoice['id'];                    // OK
        echo 'Customer: ', $invoice['customer'], "\n";       // OK - the list form
        echo (1 + $invoice['lines']) * 2;                    // OK - grouping, not a call
        echo (string) $invoice['total'];                     // OK - a cast
        echo sprintf('%0.2f', $invoice['total']);            // OK - a real call
    }
}

Remediation

Drop the parentheses. Where several values are being printed, use echo’s own comma-separated list rather than concatenating them — it avoids building the joined string at all. Where the value really is the result of a call, keep the call’s own parentheses and leave `echo bare.

<?php
echo 'Invoice ' . $invoice['id'];
echo 'Invoice ', $invoice['id'], "\n";
echo sprintf('%0.2f', $invoice['total']);

php.include_without_parens and php.return_without_parens cover the other language constructs of this family, and php.avoid_concat_echo covers concatenating what echo would take as a list.

© 2026 Xygeni. All rights reserved