Tutorials Logic, IN info@tutorialslogic.com

PHP Constants: const, define(), Scope, and Magic Constants

PHP Constant Ownership

PHP constants name process-invariant scalar or array values through top-level const declarations, runtime define calls, namespaced symbols, class constants, predefined constants, and compile-time magic constants.

Good constant design places each value with its narrowest owner, uses enums for closed domain choices, keeps runtime configuration injectable, relies on symbolic flags, labels version-specific syntax, and migrates persisted identifiers before refactoring names.

const and define()

Feature const define()
Declared Language syntax Function call
Typical location File or class declaration Runtime bootstrap logic
Class constant Yes No
Dynamic name No Yes

Application Limits

Application Limits
<?php
const MAX_LOGIN_ATTEMPTS = 5;
define('APP_ENV', 'development');

echo APP_ENV . ': ' . MAX_LOGIN_ATTEMPTS;
Output
development: 5

Class Constants

A class constant belongs to a class or interface and is accessed with ::. Use it for values that define the public vocabulary of that type.

Order Status Vocabulary

Order Status Vocabulary
<?php
final class OrderStatus
{
    public const PENDING = 'pending';
    public const PAID = 'paid';
}

echo OrderStatus::PAID;
Output
paid

Magic Constants

Magic constants change according to where PHP reads them. __DIR__ and __FILE__ are especially useful for paths and diagnostics because they do not depend on the process working directory.

Constant Value
__DIR__ Directory containing the current file
__FILE__ Full path of the current file
__LINE__ Current source line
__CLASS__ Current class name
__METHOD__ Current class method name
__NAMESPACE__ Current namespace name

Constant Mistakes

  • Do not use a constant for state that changes during a request.
  • Do not store passwords, database credentials, or API keys in committed source.
  • Avoid generic global names that can collide with library constants.
  • Use __DIR__ when requiring a file so the path does not depend on where the command started.

Constant Scope

Class constants group values with the type that owns their meaning and support visibility. Use enum cases when the value represents a closed domain choice with behavior, not a loose bag of strings. Avoid global constants for values that belong to one service or feature.

Constant names resolve through namespace rules, and dynamic constant access is harder to analyze. Do not place credentials in constants committed to source control. A constant prevents reassignment in PHP code; it does not make an array or external resource a security boundary.

Constant Semantics

A constant gives a name to a scalar or array value that cannot be redefined or unset during the script. It has no dollar sign, is case-sensitive in current PHP, and should communicate a value that is genuinely invariant for that process.

Use a variable, constructor argument, or configuration object for values that differ by request, tenant, user, test, or runtime decision. Calling changeable configuration a constant hides ownership and makes tests depend on process-global state.

An undefined constant raises an Error in PHP 8. Quote string keys and text deliberately; do not depend on the old bare-word fallback from earlier PHP releases. Use `defined()` when optional extension or deployment constants are expected.

Global constants ignore variable scope and can collide across libraries. Prefer a namespaced constant or a class/enum-owned constant when the value belongs to a domain type rather than the whole process.

  • Reserve constants for process-invariant values.
  • Use runtime configuration for changeable state.
  • Treat undefined names as errors.
  • Place constants with the narrowest meaningful owner.

Conditional and Dynamic Declarations

`const` is a declaration and is normally the clearest choice for source-defined constants. A global const declaration belongs at top-level scope; it cannot be conditionally declared inside a function, loop, or try block.

`define()` creates a named constant at runtime and can use a dynamically calculated name. Dynamic names are rarely desirable in application design because static analysis and refactoring cannot see them clearly. Use the function when runtime declaration is truly part of the integration contract.

Both forms can define scalar values and arrays under current PHP rules. Avoid resources and mutable objects as constant-like global state. An array constant cannot be reassigned, while objects reached through other constant mechanisms may still have mutable behavior depending on the feature used.

Do not guard repeated application definitions with `if (!defined(...))` merely to tolerate uncertain bootstrap order. Give one file ownership of each declaration and load it predictably; conditional definitions can conceal conflicting environments.

  • Prefer top-level const for source declarations.
  • Use define only for a justified runtime name or boundary.
  • Keep constant values simple and immutable in meaning.
  • Give every declaration one predictable owner.

Namespaces and Lookup

A namespaced constant has a qualified identity just like other namespaced symbols. Unqualified lookup inside a namespace can fall back to a global constant under PHP resolution rules, which can hide a missing local declaration.

Use explicit imports or qualified names when ownership matters, especially for library APIs. Avoid giving a local and global constant the same short name because readers cannot infer which fallback is intended.

`constant($name)` retrieves a constant when the name is known only at runtime and works with class constants and enum cases too. Validate the external discriminator against an allowlist before converting it to a constant name; do not expose arbitrary symbol lookup.

`get_defined_constants()` is a diagnostic inventory, not a configuration API. It includes engine and extension values and can reveal environment details. Keep its output out of public responses.

  • Qualify names when fallback would obscure ownership.
  • Avoid local and global short-name collisions.
  • Allowlist any dynamic constant lookup.
  • Restrict constant inventories to trusted diagnostics.

Class Constant Visibility and Lookup

A class constant belongs to a class or interface and is accessed with `::`. It can describe protocol names, fixed limits, or discriminators owned by that abstraction without creating an instance.

Visibility can make class constants public, protected, or private. Public values become part of the consumer contract; protected values support an inheritance surface; private values remain implementation detail. Changing an exposed value can still be a breaking behavioral change.

Inheritance and `self::` versus `static::` affect constant lookup. `self::` binds to the declaring class, while `static::` can use late static binding. Choose whether subclasses may specialize the value and test the consumer through the supported type.

Typed class constants are available on supported modern PHP versions and make the declared value category explicit. Version-label such syntax when a project supports older runtimes, and preserve compatible visibility and type in inheritance.

  • Own fixed domain values on the relevant type.
  • Treat public values as behavioral API.
  • Choose self or static from extension intent.
  • Label typed constant syntax by runtime support.

Enums and Constants

Use an enum case when the value represents one member of a closed domain set and callers need type-safe comparison or behavior. Use a class constant when the value is fixed metadata or a limit rather than an instance of the domain type.

Backed enum cases expose a scalar transport value, but the case identity remains the domain value. Parse external input with the enum conversion APIs and handle an unknown value instead of comparing raw strings throughout the application.

An interface constant is inherited by implementers and can create collisions or coupling when several interfaces use the same name. Prefer a dedicated enum or value type when consumers should depend on a shared concept rather than a convenience number.

Do not use a group of unrelated integer constants as a substitute for a sum type when invalid combinations are possible. Model bit flags only when combinations are meaningful and document the bitwise operations explicitly.

  • Use enum cases for closed typed choices.
  • Keep transport values separate from case identity.
  • Avoid inherited constant-name collisions.
  • Use bit flags only for valid combinations.

Predefined Constants

PHP core and loaded extensions provide predefined constants for versions, platforms, errors, filters, JSON behavior, paths, and other APIs. Availability can depend on the runtime build and loaded extension, so deployment checks should verify every required capability.

Use symbolic bitmask constants such as error or JSON flags instead of copied numeric values. Numeric values can change across PHP versions, while the symbolic name communicates intent and tracks the runtime definition.

`PHP_VERSION_ID` supports numeric version comparisons without parsing a display string, but feature detection is often stronger for extension functions, classes, or constants. Keep the application minimum version in deployment policy rather than scattering compatibility branches.

Platform constants such as directory and path separators describe process behavior. Prefer APIs that already accept portable paths, and test filesystem code on each supported operating system instead of assuming one separator solves every path rule.

  • Verify extension-owned constants during deployment.
  • Use symbolic flags rather than raw numbers.
  • Centralize minimum-version policy.
  • Test platform-sensitive behavior on supported systems.

Source Context Constants

Magic constants are compile-time contextual values. `__FILE__`, `__DIR__`, and `__LINE__` identify source location; `__FUNCTION__`, `__METHOD__`, `__CLASS__`, `__TRAIT__`, and `__NAMESPACE__` describe the declaration context; `ClassName::class` yields a qualified class-name string.

`__FILE__` and `__DIR__` refer to the file where they are written, including an included file. This makes `__DIR__` a dependable anchor for owned resources, while it should not be exposed in public error pages because it reveals server layout.

`ClassName::class` does not prove that the class exists or load it merely to create the string. It is useful for registrations and type discriminators, but persistent data should prefer a stable domain identifier if class names may change during refactoring.

On current PHP versions, `__PROPERTY__` is meaningful inside a property hook. Mark that coverage as version-specific and keep older-runtime code parseable. Magic values aid diagnostics and metaprogramming but should not replace explicit business identifiers.

  • Use source-location values for owned paths and diagnostics.
  • Do not expose physical paths to untrusted clients.
  • Treat class-name strings as refactor-sensitive metadata.
  • Version-label property-hook magic constants.

Constant Review

Test constant values where they define a public protocol, limit, or mapping. Avoid tests that merely repeat the source literal; instead verify the behavior that depends on the value and add compatibility fixtures for external formats.

Static analysis can find undefined constants, invalid access visibility, incompatible inheritance, and dead declarations. Search configuration and deployment files too, because constants consumed through dynamic strings may evade normal symbol references.

A value that developers routinely override in tests is probably a dependency or configuration value, not a constant. Replace it with an injected clock, policy, limit object, or environment adapter so tests do not require isolated processes.

During migrations, search persisted class names, serialized payloads, cache keys, and bitmask values before renaming public constants. Release mixed-version producers and consumers only when both understand the transition representation.

  • Test behavior governed by public constants.
  • Scan dynamic names and deployment configuration.
  • Inject values that tests or tenants must vary.
  • Migrate persisted identifiers before renaming symbols.
Before you move on

Mastery Check

5 checks
  • Use constants only for values that cannot vary at runtime.
  • Choose global, namespaced, class, or enum ownership deliberately.
  • Avoid arbitrary dynamic lookup and undefined names.
  • Verify predefined and extension constants at deployment.
  • Test public behavior and persisted identifiers during migrations.

Constant Boundary

  • Runtime value presented as configuration

    Constants cannot model secrets or values that vary per request. Keep environment-specific configuration outside source and validate it during bootstrap.

Try this next

Define Stable Vocabulary

0 of 2 completed

  1. Define pending, active, and archived values inside a final class and print one with ::.
  2. Use __DIR__ to create the path to config/app.php without reading the current working directory.
Browse Free Tutorials

Explore 500+ free tutorials across 20+ languages and frameworks.