PHPStatements & Semicolons

Statements & Semicolons

A PHP script is a sequence of statements — individual instructions like assigning a variable, calling a function, or looping over an array. PHP needs a way to know where one statement ends and the next begins, and unlike languages that infer this from line breaks, PHP relies on an explicit marker: the semicolon ;. Nearly every parse error a beginner hits traces back to a missing, extra, or misplaced semicolon, so it's worth understanding the rule precisely rather than by trial and error.

Every statement ends with a semicolon

Semicolons terminate statements, not lines

PHP
<?php

$firstName = 'Kwame';
$lastName = 'Nkrumah';
$fullName = $firstName . ' ' . $lastName;

echo $fullName;

Note that this is per statement, not per line — you can put multiple statements on one physical line as long as each ends with its own semicolon, though doing so hurts readability and no real-world style guide recommends it.

Legal but discouraged

PHP
<?php

$a = 1; $b = 2; $c = $a + $b;
echo $c;
Constructs that don't need one after them

The rule isn't "every line needs a semicolon" — it's "every simple statement needs one." Control structures like if, foreach, while, and function/class definitions are themselves block structures, and the block's closing brace } is what ends them, not a semicolon.

No semicolon after a closing brace

PHP
<?php

function isEven(int $n): bool
{
    return $n % 2 === 0;
}

if (isEven(4)) {
    echo 'Even';
} else {
    echo 'Odd';
}
// Note: no ";" after either closing "}" above.
The closing ?> tag implies a semicolon

PHP's closing tag, ?>, automatically terminates the statement immediately before it — you're allowed to omit the final semicolon if a closing tag follows right after.

The closing tag makes the last semicolon optional

PHP
<?php echo 'Hello' ?>
<p>Some HTML follows the PHP block.</p>

This shortcut is convenient in short embedded snippets but easy to misuse the moment you add another statement afterward and forget the semicolon that's now required between two statements rather than before a tag.

This breaks — the omitted semicolon was only safe before ?>

PHP
<?php
$greeting = 'Hello'
$name = 'world' ?>
<!-- Parse error: syntax error, unexpected variable "$name" -->
"Unexpected end of file" — the usual causes

This error means the parser reached the end of the script while still expecting something to close — almost always a missing semicolon, brace, parenthesis, or bracket somewhere earlier. Because PHP reports the error at the end of the file rather than at the actual mistake, it's one of the more frustrating messages for newcomers.

  • A missing semicolon on a statement, which makes the parser fold the next line into the same statement until something breaks.

  • An unclosed { for a function, class, if, or loop body — count your braces, or let your editor's bracket-matching do it.

  • A string that was opened with a quote and never closed, silently swallowing the rest of the file as string content.

  • An unclosed ( in a function call or condition, especially inside a long chained expression.

A missing semicolon cascades into a confusing error

PHP
<?php

function calculateTotal(array $prices): float
{
    $sum = array_sum($prices)   // <-- missing semicolon here
    return $sum * 1.08;
}

echo calculateTotal([10, 20, 30]);
// PHP Parse error: syntax error, unexpected token "return"
Read parse errors from the top down, not just the reported line
When you see "unexpected end of file" or "unexpected token" on a line far from the real bug, start checking a few statements *above* that line, not below it — the parser only notices something is wrong once it runs out of file to keep parsing.
PSR-12: omit the closing tag in pure-PHP files

For any file that contains only PHP code — a class file, a function library, anything without trailing HTML — the PSR-12 coding standard recommends omitting the closing ?> tag entirely. This isn't stylistic pedantry: a file that ends with ?> can have trailing whitespace or a newline after the tag, and if that file is ever included or required, that stray whitespace gets sent straight to the output buffer — which breaks things like sending HTTP headers or cookies after the include, because output has already started.

Idiomatic pure-PHP file (PSR-12 style)

PHP
<?php

declare(strict_types=1);

namespace App\Billing;

class InvoiceTotal
{
    public function __construct(
        private readonly float $subtotal,
        private readonly float $taxRate,
    ) {
    }

    public function total(): float
    {
        return $this->subtotal * (1 + $this->taxRate);
    }
}
// File simply ends here — no closing ?> tag.
Trailing whitespace after ?> is a classic 'headers already sent' bug
If a shared config file ends with `?>\n` (a newline after the closing tag) and gets `require`d before a `header()` or `session_start()` call elsewhere, PHP will throw "Cannot modify header information — headers already sent", because that trailing newline was already flushed to the response. Omitting the closing tag in pure-PHP files removes the possibility entirely.
  • Every simple statement (assignment, function call, return, etc.) must end in ;.

  • Block structures (if, loops, function/class bodies) end with }, not a semicolon.

  • The closing ?> tag implicitly terminates the statement right before it.

  • "Unexpected end of file" almost always means an unclosed brace, bracket, string, or a missing semicolon somewhere earlier in the file.

  • PSR-12 recommends omitting the closing ?> tag in files that contain only PHP.

Tip
Configure your editor to show matching brace/bracket pairs and to lint on save (`php -l file.php` catches syntax errors in milliseconds, before you even run the script). Catching a missing semicolon at save-time is far cheaper than debugging a cryptic "unexpected end of file" ten minutes later.