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, andfunction, notTRUEorFOREACH. - Treat context-sensitive keywords like
enum,readonly, andmatchas 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
matchexpression adefaultarm unless you have deliberately enumerated every possible value and want an error on anything unexpected. - Prefer
elseif(one word) overelse if(two words with a nested block) for flat conditional chains – both work, butelseifmore clearly signals a single chain to readers. - Use
try/catch/finallyto handle exceptional, not routine, control flow; for expected branching, keywords likeifandmatchare 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
- Write a function
describeNumber(int $n): stringthat usesif,elseif, andelseto return"negative","zero", or"positive"depending on the sign of$n. - Rewrite the same function using
matchinstead ofif/elseif/else. Hint: you’ll need comparison expressions as the match subject, e.g.match (true) { $n < 0 => ..., }. - Try declaring a class named
Interfacein a local PHP file and run it through the command line withphp -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, andneverare context-sensitive (“semi-reserved”) to preserve backward compatibility. - Internally, each keyword becomes its own dedicated token (like
T_IForT_CLASS) during lexing, which is why the parser can distinguish keywords from ordinary identifiers. - The
matchkeyword uses strict comparison and throwsUnhandledMatchErrorif no arm applies and there’s nodefault.
