PHP Constants
A constant in PHP is a name or identifier bound to a fixed value that cannot change once it is set. Unlike variables, constants have no $ prefix, are globally accessible from anywhere in a script once defined (unless declared inside a class), and are ideal for values that should never change during execution — configuration flags, mathematical values, status codes, and API settings. Understanding constants well helps you write code that is safer against accidental reassignment and easier for other developers to reason about.
Overview: How Constants Work
PHP gives you two ways to declare a constant: the define() function and the const keyword. Both create an immutable binding, but they behave differently under the hood.
define('NAME', value) is a regular function call. Because it is a function call, PHP evaluates it at runtime, in the order the interpreter reaches that line. This means you can call define() conditionally — inside an if statement, inside a loop, or inside a function — and the constant only comes into existence once that line actually executes.
The const keyword, by contrast, is a language construct handled at compile time when used at the top level of a file or inside a class/interface/trait/enum. Because the Zend Engine resolves const declarations while compiling the script (before any code actually runs), the value must be a constant expression — a literal, or an expression built from literals and other constants (arithmetic, array literals, and even the ternary/match operators are allowed in modern PHP) — not something that depends on runtime data like a function call result or user input. This is also why plain const statements cannot appear inside if, for, or function bodies outside of a class: the compiler needs to know about them before the code runs, independent of control flow.
Once a constant exists, it lives for the entire lifetime of the request. There is no way to unset() it, and any attempt to reassign it is either a parse error (if you try to use assignment syntax on it) or, for define(), a warning that the redefinition is ignored. This immutability is the entire point of a constant: once set, its value is a guarantee the rest of the program can rely on.
Class Constants
Constants declared with const inside a class, interface, trait, or enum belong to that class rather than to the global namespace. They are accessed with the scope resolution operator ::, e.g. ClassName::CONST_NAME, and from inside the class itself you should use self::CONST_NAME or, if you want late static binding to resolve the constant on the calling subclass, static::CONST_NAME. Since PHP 7.1, class constants can have visibility modifiers (public, protected, private); since PHP 8.3, you can mark a class constant final so that subclasses cannot override it.
Syntax
define(string $name, mixed $value);
const NAME = value;
class Example {
[visibility] [final] const NAME = value;
}
- define(‘NAME’, value) — the first argument is the constant’s name as a string; the second is its value. Evaluated at runtime, so it can be conditional.
- const NAME = value; — the compile-time form. The name is a bare identifier (no quotes, no
$). Only allowed at the top level of a file/namespace or inside a class-like declaration. - value — must be a scalar (
int,float,string,bool),null, an array, or (forconst) a constant expression involving those types. - visibility (class constants only) —
public(default),protected, orprivate, controlling which code can read the constant. - final (class constants, PHP 8.3+) — prevents a subclass from redeclaring the constant with a different value.
Examples
Example 1: Basic Constants with define() and const
<?php
define('SITE_NAME', 'Programming Line');
const MAX_USERS = 100;
echo SITE_NAME . "\n";
echo MAX_USERS . "\n";
echo SITE_NAME . " allows up to " . MAX_USERS . " users.\n";
Output:
Programming Line
100
Programming Line allows up to 100 users.
Both define() and const create constants that behave identically once defined: they are referenced by their bare name, with no $ sigil, and PHP substitutes their value wherever they appear.
Example 2: Class Constants with match()
<?php
class HttpStatus
{
const OK = 200;
const NOT_FOUND = 404;
final public const SERVER_ERROR = 500;
}
function describeStatus(int $code): string
{
return match ($code) {
HttpStatus::OK => 'OK',
HttpStatus::NOT_FOUND => 'Not Found',
HttpStatus::SERVER_ERROR => 'Internal Server Error',
default => 'Unknown',
};
}
echo describeStatus(HttpStatus::OK) . "\n";
echo describeStatus(404) . "\n";
echo HttpStatus::SERVER_ERROR . "\n";
Output:
OK
Not Found
500
Grouping related constants inside a class (here, HTTP status codes) keeps them namespaced and self-documenting. Marking SERVER_ERROR as final (PHP 8.3+) guarantees that no subclass of HttpStatus can silently change its meaning.
Example 3: Interface Constants and Array Constants
<?php
interface Configurable
{
const DEFAULT_TIMEOUT = 30;
}
class ApiClient implements Configurable
{
const BASE_URL = 'https://api.example.com';
const ALLOWED_METHODS = ['GET', 'POST', 'PUT', 'DELETE'];
const RATE_LIMIT_WINDOW = 60 * 60;
}
function isMethodAllowed(string $method): bool
{
return in_array($method, ApiClient::ALLOWED_METHODS, true);
}
echo ApiClient::BASE_URL . "\n";
echo Configurable::DEFAULT_TIMEOUT . "\n";
var_dump(isMethodAllowed('POST'));
var_dump(isMethodAllowed('PATCH'));
Output:
https://api.example.com
30
bool(true)
bool(false)
Constants can hold arrays, not just scalars, which is useful for whitelists like ALLOWED_METHODS. Notice that RATE_LIMIT_WINDOW is computed from a constant expression (60 * 60) — that arithmetic runs once, at compile time, not on every request. Interface constants like DEFAULT_TIMEOUT are inherited by every implementing class and can also be read directly through the interface name.
Under the Hood
When the Zend Engine compiles a script, it maintains a symbol table for constants separate from the one used for variables. Constants declared with const at the top level are resolved during compilation, so by the time execution begins, the engine already knows their names and values. Constants declared with define() are inserted into that same table as the define() call executes, which is why they can depend on runtime logic (environment variables, conditionals, computed values) — something plain top-level const cannot do.
Class constants are stored on the class’s own metadata structure rather than in the global constant table, which is why they require the :: operator and a class/interface name (or self::/static::) to resolve — PHP has to look them up on that specific class, not in the global namespace. PHP also exposes a family of "magic constants" that are not stored values at all but are substituted by the compiler based on where they appear in the source: __LINE__, __FILE__, __DIR__, __FUNCTION__, __CLASS__, __METHOD__, __NAMESPACE__, and __TRAIT__. These are useful for logging and debugging because their value changes depending on the exact line, file, or function they are written in.
| Magic Constant | Resolves To |
|---|---|
__LINE__ |
The current line number in the file |
__FILE__ |
The full path and filename of the file |
__DIR__ |
The directory of the file (equivalent to dirname(__FILE__)) |
__FUNCTION__ |
The name of the current function |
__CLASS__ |
The name of the current class |
__METHOD__ |
The class and method name, e.g. Class::method |
__NAMESPACE__ |
The name of the current namespace |
Common Mistakes
Mistake 1: Trying to reassign a constant
Constants are not variables. Attempting to assign a new value to one using = is not just discouraged, it is invalid syntax and will not even parse:
<?php
define('MAX_USERS', 100);
MAX_USERS = 200;
echo MAX_USERS;
PHP raises a parse error here because MAX_USERS is a bare identifier, not a valid assignment target — the engine has no concept of "assign to a constant." If a value genuinely needs to change during execution, it should be a variable, not a constant:
<?php
$maxUsers = 100;
$maxUsers = 200;
echo $maxUsers;
Output:
200
Mistake 2: Forgetting self:: when referencing a class constant
Inside a class method, writing the constant’s bare name without self:: does not refer to the class constant — PHP looks for a global constant of that name instead, which usually does not exist:
<?php
class Circle
{
const PI = 3.14159;
public function area(float $radius): float
{
return PI * $radius * $radius;
}
}
$circle = new Circle();
echo $circle->area(2);
This code parses fine but fails at runtime with Error: Undefined constant "PI", because PI alone is treated as a lookup in the global constant table, not the class. The fix is to always qualify class constants with self:: (or static:: for late static binding):
<?php
class Circle
{
const PI = 3.14159;
public function area(float $radius): float
{
return self::PI * $radius * $radius;
}
}
$circle = new Circle();
echo $circle->area(2);
Output:
12.56636
Best Practices
- Use
constfor values known at compile time (most config-like values); reservedefine()for cases that genuinely need runtime logic, such as conditionally defining a constant based on the environment. - Name constants in
UPPER_SNAKE_CASEto visually distinguish them from variables and function calls at a glance. - Group related constants inside a class, interface, or PHP 8.1+ enum instead of scattering global constants, to avoid name collisions and improve discoverability.
- Mark class constants
final(PHP 8.3+) when subclasses should never be able to override their meaning, especially for values like status codes that other code depends on. - Prefer typed, self-documenting constant names (
MAX_LOGIN_ATTEMPTS) over "magic numbers" scattered through business logic. - Avoid relying on case-insensitive constant lookups — PHP removed that feature entirely as of PHP 8.0, so constant names are always case-sensitive today.
- Use
defined('NAME')to check whether a constant already exists before defining it, if there is any chance the same script or included file could run twice.
Practice Exercises
- Define a global constant
APP_VERSIONholding a version string withconst, then write a function that echoes a message including that version using string concatenation. - Create a class
Temperaturewith a constantFREEZING_POINT_CELSIUSset to0and a methodisFreezing(float $celsius): boolthat compares its parameter against the constant usingself::. Test it with a few values. - Write an interface
Shapewith a constantUNITS = 'metric', implement it in two classes, and print the constant through both the interface name and each implementing class name to confirm they resolve to the same value.
Summary
- Constants hold values that cannot change after being defined, and are referenced without a
$prefix. define()is a runtime function call and can be used conditionally;constis resolved at compile time and must use constant expressions.- Class constants are declared with
constinside a class/interface/trait/enum and accessed viaClassName::CONST, orself::CONST/static::CONSTfrom inside the class. - Since PHP 7.1, class constants support visibility modifiers; since PHP 8.3, they support
final. - Magic constants like
__LINE__and__CLASS__are compiler substitutions, not stored values, and change based on where they appear in the source. - Attempting to reassign a constant is a parse error; forgetting
self::inside a class is a common runtime bug, not a syntax error. - Constant names are always case-sensitive as of PHP 8.0.
