PHP Keywords Reference

A keyword is a word that the PHP language itself has claimed a special meaning for – things like if, class, function, and try. Because the parser treats these words as instructions rather than plain text, you cannot use them as the name of a variable, function, class, constant, or method. Understanding the full list of PHP keywords, how the parser recognizes them, and where beginners typically trip over them will save you from confusing “Fatal error: Cannot use … as …” messages later on.

Overview: What Are PHP Keywords?

PHP keywords are reserved words that the Zend engine’s lexer (the part of PHP that reads your source code) recognizes as distinct tokens rather than ordinary text. When the lexer sees if, it does not treat it as an identifier – it emits a special token (internally something like T_IF) that the parser understands as “begin a conditional branch.” This is exactly why if cannot double as a variable or function name: the grammar has already decided what that word means before your code ever runs. PHP currently reserves more than 80 keywords, spanning control flow (if, foreach, switch), declarations (class, function, interface), exception handling (try, catch, throw), and literal values (true, false, null).

Two details make keywords behave differently from ordinary identifiers. First, keywords are case-insensitive: IF, If, and if are the exact same token, and the same is true for class and function names. Variable names and array keys, by contrast, are case-sensitive – $name and $Name are two different variables. Second, PHP has a category of context-sensitive (“semi-reserved”) keywords added in recent versions – enum, readonly, match, fn, and never among them. These are only special in the positions where they carry meaning, which lets older code that happened to use them as method names keep working. It’s also worth separating keywords from two lookalike categories: magic constants such as __LINE__ and __CLASS__ are compile-time constants, not keywords, and superglobals such as $_GET and $_SESSION are just predefined variables, not reserved words.

Syntax: Keyword Categories

There is no single “syntax” for a keyword the way there is for a function call – each keyword has its own grammar. What matters is knowing which category a keyword belongs to, since that tells you where it is legal to use it.

Category Keywords
Control flow if, else, elseif, switch, case, default, while, do, for, foreach, break, continue, goto, match
Declarations & OOP class, interface, trait, enum, extends, implements, abstract, final, public, protected, private, static, const, var, readonly, function, fn, return, new, clone, instanceof, use, namespace, global, yield
Exception handling try, catch, finally, throw
Including files include, include_once, require, require_once
Language constructs echo, print, isset, unset, empty, exit, die, list, array, and, or, xor
Values & special references true, false, null, self, parent, static (as a class reference)

Every construct below draws its vocabulary from this table. For example, a conditional and a function declaration are built entirely from keywords plus your own identifiers:

<?php
$score = 73;

if ($score >= 90) {
    echo "Grade: A";
} elseif ($score >= 70) {
    echo "Grade: B";
} else {
    echo "Grade: C";
}
echo "\n";

function greet(string $name): string
{
    return "Hello, $name!";
}

echo greet("World");
Output:
Grade: B
Hello, World!

Examples

Example 1: Control-Flow Keywords

<?php
$grade = 82;

if ($grade >= 90) {
    echo "A";
} elseif ($grade >= 80) {
    echo "B";
} else {
    echo "C";
}

echo "\n";

$fruits = ["apple", "banana", "cherry"];
foreach ($fruits as $index => $fruit) {
    if ($fruit === "banana") {
        continue;
    }
    echo "$index: $fruit\n";
}

$day = "Tue";
$label = match ($day) {
    "Mon", "Tue", "Wed", "Thu", "Fri" => "Weekday",
    "Sat", "Sun" => "Weekend",
    default => "Unknown",
};
echo $label . "\n";
Output:
B
0: apple
2: cherry
Weekday

This example leans on five keywords at once: if/elseif/else pick a branch, foreach walks the array while continue skips the “banana” iteration, and match (PHP 8.0+) returns a value based on strict comparison against the listed cases, falling back to default when nothing matches.

Example 2: Declaration Keywords for Classes

<?php
interface Shape
{
    public function area(): float;
}

abstract class BaseShape implements Shape
{
    public function describe(): string
    {
        return static::class . " has area " . $this->area();
    }
}

final class Circle extends BaseShape
{
    public function __construct(private readonly float $radius)
    {
    }

    public function area(): float
    {
        return M_PI * $this->radius ** 2;
    }
}

$circle = new Circle(2.0);
echo $circle->describe() . "\n";
echo get_parent_class($circle) . "\n";
Output:
Circle has area 12.566370614359
BaseShape

Here, interface, abstract, implements, extends, and final are all declaration keywords that shape how classes relate to one another: Circle is final (cannot be subclassed further), it extends the abstract base, and the base implements the interface’s contract. The readonly modifier (PHP 8.1+) is a context-sensitive keyword that makes the promoted $radius property writable only once, from inside the constructor.

Example 3: Exception-Handling Keywords

<?php
function divide(int $a, int $b): int
{
    if ($b === 0) {
        throw new DivisionByZeroError("Cannot divide by zero");
    }
    return intdiv($a, $b);
}

try {
    echo divide(10, 2) . "\n";
    echo divide(5, 0) . "\n";
} catch (DivisionByZeroError $e) {
    echo "Error: " . $e->getMessage() . "\n";
} finally {
    echo "Done\n";
}
Output:
5
Error: Cannot divide by zero
Done

The try/catch/finally keywords define a protected region: code inside try runs normally until a throw statement raises an object, at which point control jumps straight to a matching catch block, skipping any remaining lines in try. The finally block always runs afterward, whether or not an exception occurred.

How PHP Parses Keywords (Under the Hood)

Before your script executes, PHP runs it through a tokenizer (a lexer built with tools like re2c) that scans the raw text character by character and groups it into tokens. Ordinary words become a generic T_STRING token, but reserved keywords each get their own dedicated token constant – if becomes T_IF, foreach becomes T_FOREACH, class becomes T_CLASS, and so on. You can see this yourself with the built-in token_get_all() function, which returns the exact token stream PHP produced for a piece of source code.

This token distinction is precisely why keywords are off-limits as identifiers: the grammar (implemented with a parser generator) has separate rules for “a T_CLASS token starts a class declaration” versus “a T_STRING token is a name,” and mixing the two would make the language ambiguous to parse. Once tokenized and parsed into an abstract syntax tree, PHP compiles that tree into Zend opcodes, which the Zend Virtual Machine then executes. All of this happens before a single line of your logic actually runs, which is also why keyword-related errors (like using a reserved word as a class name) are reported as fatal compile-time errors rather than runtime exceptions.

Common Mistakes

Mistake 1: Using a Reserved Word as an Identifier

Reserved keywords cannot be used as class, interface, trait, or (in most cases) method names, even if the name seems descriptive:

<?php
class List
{
    public function add($item)
    {
        // ...
    }
}

This fails to compile with a fatal error because list is a reserved language construct, not an available identifier. The fix is simply to pick a name that isn’t on the reserved list:

<?php
class ItemList
{
    public function add($item)
    {
        // add item to the list
    }
}

$list = new ItemList();
$list->add("first");
echo "Added successfully";
Output:
Added successfully

Mistake 2: Forgetting That match Has No Fallthrough or Implicit Default

Unlike switch, the match keyword uses strict (===) comparison and throws an error instead of silently doing nothing when no arm matches:

<?php
function shippingCost(string $region): float
{
    return match ($region) {
        "US" => 5.00,
        "EU" => 8.50,
        "APAC" => 9.75,
    };
}

echo shippingCost("LATAM");

Calling this with "LATAM" throws an uncaught UnhandledMatchError because none of the listed cases apply and there is no default arm. Adding a default fixes it:

<?php
function shippingCost(string $region): float
{
    return match ($region) {
        "US" => 5.00,
        "EU" => 8.50,
        "APAC" => 9.75,
        default => 12.00,
    };
}

echo shippingCost("LATAM");
Output:
12

Best Practices

  • Never name variables, functions, classes, or constants after a reserved keyword – if a name feels natural but PHP rejects it, it’s very likely on the reserved list.
  • Remember that keywords are case-insensitive but stylistic convention (and most style guides, including PSR-12) call for lowercase: use true, foreach, and function, not TRUE or FOREACH.
  • Treat context-sensitive keywords like enum, readonly, and match as fully reserved in new code, even though PHP still tolerates them as identifiers in a few legacy positions – relying on that leniency makes code harder to read.
  • Always give a match expression a default arm unless you have deliberately enumerated every possible value and want an error on anything unexpected.
  • Prefer elseif (one word) over else if (two words with a nested block) for flat conditional chains – both work, but elseif more clearly signals a single chain to readers.
  • Use try/catch/finally to handle exceptional, not routine, control flow; for expected branching, keywords like if and match are almost always clearer and faster.
  • When in doubt about whether a word is reserved, check the current PHP manual’s “List of Keywords” page for your target PHP version, since the list grows with each release.

Practice Exercises

  1. Write a function describeNumber(int $n): string that uses if, elseif, and else to return "negative", "zero", or "positive" depending on the sign of $n.
  2. Rewrite the same function using match instead of if/elseif/else. Hint: you’ll need comparison expressions as the match subject, e.g. match (true) { $n < 0 => ..., }.
  3. Try declaring a class named Interface in a local PHP file and run it through the command line with php -l yourfile.php. Read the exact error PHP gives you, then rename the class to something valid and confirm the error disappears.

Summary

  • Keywords are reserved words the PHP parser assigns special meaning to; they cannot be used as variable, function, class, or constant names.
  • PHP has over 80 keywords covering control flow, OOP declarations, exception handling, includes, and language constructs.
  • Keywords are case-insensitive, unlike variable names, which are case-sensitive.
  • Newer keywords such as enum, readonly, match, fn, and never are context-sensitive (“semi-reserved”) to preserve backward compatibility.
  • Internally, each keyword becomes its own dedicated token (like T_IF or T_CLASS) during lexing, which is why the parser can distinguish keywords from ordinary identifiers.
  • The match keyword uses strict comparison and throws UnhandledMatchError if no arm applies and there’s no default.