objects namespaces and application architecture

Class Constants

Class constants are fixed values that belong to a class. They are useful for names, limits, keys, status strings, default values, and other facts that should not change at runtime.

Use a class constant when the value is part of the class's meaning. Use configuration when the value changes between environments. Use an enum when the value belongs to a closed set with stronger typing.

Define And Read A Constant

Constants are accessed with ClassName::CONSTANT_NAME.

PHP example
<?php

declare(strict_types=1);

class Invoice
{
    public const DEFAULT_CURRENCY = 'GBP';
}

echo Invoice::DEFAULT_CURRENCY . PHP_EOL;

// Prints:
// GBP

By convention, constant names are uppercase with underscores.

Use Constants For Shared Status Values

Constants reduce repeated string literals.

PHP example
<?php

declare(strict_types=1);

class OrderStatus
{
    public const DRAFT = 'draft';
    public const PAID = 'paid';
    public const CANCELLED = 'cancelled';
}

$status = OrderStatus::PAID;

echo $status . PHP_EOL;

// Prints:
// paid

This is clearer than scattering 'paid' through controllers, services, tests, and templates.

Use self:: Inside The Class

Inside the class, refer to constants with self::.

PHP example
<?php

declare(strict_types=1);

class PasswordPolicy
{
    public const MIN_LENGTH = 12;

    public function isLongEnough(string $password): bool
    {
        return strlen($password) >= self::MIN_LENGTH;
    }
}

$policy = new PasswordPolicy();

echo $policy->isLongEnough('correct horse') ? 'accepted' : 'too short';
echo PHP_EOL;

// Prints:
// accepted

The method and the constant stay connected inside the same class.

Constants Can Have Visibility

Modern PHP supports visibility on class constants.

PHP example
<?php

declare(strict_types=1);

class TokenGenerator
{
    private const TOKEN_BYTES = 16;

    public function tokenLength(): int
    {
        return self::TOKEN_BYTES * 2;
    }
}

$generator = new TokenGenerator();

echo $generator->tokenLength() . PHP_EOL;

// Prints:
// 32

Private constants are useful when the value is an implementation detail rather than part of the public API.

A class that only contains constants can be useful, but it can also become a dumping ground.

PHP example
<?php

declare(strict_types=1);

class MimeTypes
{
    public const PDF = 'application/pdf';
    public const CSV = 'text/csv';
    public const JSON = 'application/json';
}

echo MimeTypes::PDF . PHP_EOL;

// Prints:
// application/pdf

Keep constant-only classes focused. MimeTypes is clearer than a broad AppConstants class.

Know When An Enum Is Better

Constants are simple strings or numbers. Enums give a closed set of typed cases.

PHP example
<?php

declare(strict_types=1);

class LegacyPaymentStatus
{
    public const PENDING = 'pending';
    public const PAID = 'paid';
}

echo LegacyPaymentStatus::PENDING . PHP_EOL;

// Prints:
// pending

You will learn enums later. For now, understand that class constants are common in existing codebases and older PHP versions.

What To Remember

Class constants name fixed values that belong to a class. Use them to avoid repeated magic strings and numbers, keep related values together, choose visibility deliberately, and avoid turning one constants class into a global junk drawer.

Practice

Task: Validate Order Status

Create a small class that defines allowed order statuses.

Requirements

  • Use declare(strict_types=1);.
  • Create an OrderStatus class.
  • Add public constants for draft, paid, and cancelled.
  • Add a public static method that returns all allowed statuses.
  • Add a public static method that checks whether a status is allowed.
  • Print the allowed statuses.
  • Check one valid status and one invalid status.
  • Include the expected output as comments in the same PHP code block.

The goal is to avoid repeated status strings in calling code.

Show solution
PHP example
<?php

declare(strict_types=1);

class OrderStatus
{
    public const DRAFT = 'draft';
    public const PAID = 'paid';
    public const CANCELLED = 'cancelled';

    public static function all(): array
    {
        return [
            self::DRAFT,
            self::PAID,
            self::CANCELLED,
        ];
    }

    public static function isAllowed(string $status): bool
    {
        return in_array($status, self::all(), true);
    }
}

echo implode(', ', OrderStatus::all()) . PHP_EOL;
echo OrderStatus::isAllowed(OrderStatus::PAID) ? 'paid is allowed' : 'paid is rejected';
echo PHP_EOL;
echo OrderStatus::isAllowed('refunded') ? 'refunded is allowed' : 'refunded is rejected';
echo PHP_EOL;

// Prints:
// draft, paid, cancelled
// paid is allowed
// refunded is rejected

The constants put the repeated strings in one place. Calling code can use OrderStatus::PAID instead of typing 'paid' by hand each time.