No Fallthrough

ID

php.no_fallthrough

Severity

low

Remediation Complexity

trivial

Remediation Risk

low

Remediation Effort

low

Resource

Reliability

Language

Php

Tags

reliability, switch

Description

Reports a non-empty switch case whose statement list does not end in a control-flow terminator (break, return, throw, continue, goto, or exit/die) and that is followed by another case or the default clause. Execution then falls through into the next case, which is almost always unintended.

Rationale

Unlike many languages, PHP switch cases do not stop at the end of their body: once a matching case runs to its last statement, control continues into the following case unless a terminator is reached. A missing break therefore executes code meant for a different case, producing subtle, hard-to-find bugs. Intentional grouping with empty cases (case A: case B:) is fine and is not reported, and the final block is never flagged because there is nothing after it to fall into.

<?php
switch ($code) {
    case 1:
        $a = doOne();   // FLAW — no break, falls into case 2
    case 2:
        return doTwo(); // OK — ends in return
    case 3:
    case 4:             // OK — empty grouped case, deliberate fall-through
        handle();
        break;          // OK — ends in break
    default:
        reset();
        break;
}

Remediation

Add an explicit terminator (break, return, throw, …​) as the last statement of every non-empty case. If the fall-through is intentional, leave the case body empty so it groups with the next case, or restructure the logic to make the shared handling explicit.