PHPWhitespace & Formatting

Whitespace & Formatting

PHP's parser doesn't care about spaces, tabs, blank lines, or how many of each sit between tokens — it cares about semicolons, braces, and keywords. That's called whitespace insensitivity, and it means you could write an entire application as one unreadable line and PHP would run it exactly the same as a beautifully indented version. The parser's indifference is precisely why formatting conventions matter more, not less: nothing forces consistency except the team's discipline and its tooling.

PHP genuinely doesn't care

Both of these run identically

PHP
<?php
function add(int $a,int $b):int{return $a+$b;}
echo add(2,3);

Same logic, formatted for humans

PHP
<?php

function add(int $a, int $b): int
{
    return $a + $b;
}

echo add(2, 3);

Both scripts print the same result. The difference isn't in what PHP does with them — it's in how long it takes the next developer (including future you) to understand what's happening, spot a bug, or safely modify the logic.

Where whitespace is required, not optional

"Whitespace-insensitive" doesn't mean whitespace is never meaningful — it's required as a separator wherever removing it would merge two tokens into one. Between adjacent keywords and identifiers, at least one space (or newline) is mandatory.

Whitespace as a required separator

PHP
<?php

// Required: without a space, "returntrue" would be read as one identifier
function isActive(): bool
{
    return true;
}

// Not required: operators and punctuation are unambiguous on their own
$total=1+2;   // legal, just hard to read
$total = 1 + 2; // same result, readable
PSR-12: the community formatting standard

PSR-12 is the PHP-FIG's coding style standard, and it's what nearly every modern framework, Composer package, and open-source PHP project formats its code to. Following it means any PHP developer can open your file and immediately feel at home, without adapting to a personal or team-specific dialect of "readable."

  • Indent with 4 spaces, never tabs.

  • Opening braces for classes and functions go on their own line; braces for control structures (if, foreach, while) go on the same line as the keyword.

  • One statement per line, and one blank line to separate logical sections — not stacks of blank lines.

  • A single space after commas in argument lists, and around binary operators like =, +, ., and ===.

  • Lines should generally stay under ~120 characters; break long argument lists one-per-line when they get unwieldy.

PSR-12 brace placement: classes/functions vs. control structures

PHP
<?php

class OrderProcessor
{                                    // class: brace on its own line
    public function process(array $items): float
    {                                // function: brace on its own line
        $total = 0.0;

        foreach ($items as $item) { // control structure: brace on same line
            $total += $item['price'] * $item['qty'];
        }

        if ($total > 100) {         // same rule for if/else
            $total *= 0.95;
        } else {
            $total += 5.00;
        }

        return $total;
    }
}
Long argument lists and method chains

When a function call or chained expression gets too wide for one readable line, PSR-12 favors breaking after the opening parenthesis and putting each argument (or each chained call) on its own indented line, with the closing parenthesis aligned back to the start.

Breaking a long call across lines

PHP
<?php

$invoice = createInvoice(
    customerId: 4821,
    items: $cartItems,
    currency: 'USD',
    dueInDays: 30,
);

$query = $db->table('orders')
    ->where('status', 'pending')
    ->whereDate('created_at', '>=', $since)
    ->orderBy('created_at', 'desc')
    ->get();
Formatting rules across languages: a quick reference

Concern

PSR-12 rule

Indentation

4 spaces, no tabs

Class/function brace

own line

Control structure brace (if/foreach/while)

same line as keyword

Space after commas

yes, one space

Space around =, ., ===, etc.

yes, one space each side

Trailing whitespace on a line

not allowed

Let tooling enforce it, don't rely on memory

No developer reliably remembers every PSR-12 rule while typing, and no team should rely on code review to catch formatting drift. Automated formatters exist precisely so that style is a solved problem, applied consistently and mechanically:

  • PHP_CodeSniffer (phpcs/phpcbf) — detects PSR-12 violations and can auto-fix most of them.

  • PHP-CS-Fixer — a more configurable formatter that can enforce PSR-12 plus many additional, opinionated rules.

  • Editor integrations for both tools reformat on save, so nobody has to think about brace placement again.

Running PHP-CS-Fixer against PSR-12

Bash
composer require --dev friendsofphp/php-cs-fixer

# Preview what would change
vendor/bin/php-cs-fixer fix --dry-run --diff --rules=@PSR12 src/

# Actually apply the fixes
vendor/bin/php-cs-fixer fix --rules=@PSR12 src/
Formatting tools don't replace static analysis
`php-cs-fixer` and `phpcs` only fix how code *looks* — spacing, braces, blank lines. They won't catch a wrong variable type or an unreachable branch. Pair them with a static analyser like PHPStan or Psalm, which reason about what the code actually *does*.
  • PHP ignores whitespace between tokens except where it's needed to separate two identifiers/keywords.

  • Formatting exists entirely for human readability, not for the interpreter.

  • PSR-12 is the de facto community standard: 4-space indents, braces on their own line for classes/functions but the same line for control structures.

  • Automate formatting with php-cs-fixer or phpcs rather than relying on manual discipline.

Tip
Add a formatter to a pre-commit hook (Husky-style, or a Composer script wired into your CI pipeline) rather than a manual "please run the formatter" step in your contributing guide. A rule that isn't enforced automatically gets skipped under deadline pressure — and that's exactly when formatting drift creeps in.