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 (for const) a constant expression involving those types.
  • visibility (class constants only) — public (default), protected, or private, 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 const for values known at compile time (most config-like values); reserve define() for cases that genuinely need runtime logic, such as conditionally defining a constant based on the environment.
  • Name constants in UPPER_SNAKE_CASE to 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_VERSION holding a version string with const, then write a function that echoes a message including that version using string concatenation.
  • Create a class Temperature with a constant FREEZING_POINT_CELSIUS set to 0 and a method isFreezing(float $celsius): bool that compares its parameter against the constant using self::. Test it with a few values.
  • Write an interface Shape with a constant UNITS = '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; const is resolved at compile time and must use constant expressions.
  • Class constants are declared with const inside a class/interface/trait/enum and accessed via ClassName::CONST, or self::CONST/static::CONST from 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.