Константы классов в объектно-ориентированном программировании на PHP

Раздел: ООП в PHP -> Константы

Константы классов в PHP: синтаксис и возможности

Константы классов в PHP объявляются с помощью ключевого слова const внутри класса. Они принадлежат классу, а не объекту, и не могут быть изменены после объявления. Для доступа к константе используется имя класса и оператор :: (Paamayim Nekudotayim).


<?php
class MyClass
{
    const PI = 3.14159;
    const GREETING = 'Hello, world!';
}

echo MyClass::PI;         // 3.14159
echo MyClass::GREETING;   // Hello, world!

Php class constant (константы классов в php)

В PHP 7.1.0 появилась возможность указывать модификаторы доступа (public, protected, private) для констант. По умолчанию константа считается public.


class MyClass
{
    public const PUBLIC_CONST = 1;
    protected const PROTECTED_CONST = 2;
    private const PRIVATE_CONST = 3;
}

Includes defines php (подключения и определения в php)

Константы могут быть объявлены с использованием скалярных выражений (числа, строки, константы и их комбинации, за исключением функций и вызовов методов).


class MathConstants
{
    const HALF = 0.5;
    const DOUBLE = 2 * self::HALF;
}

Для обращения к константе внутри класса используется ключевое слово self. В наследовании константа может быть переопределена в дочернем классе (только если она не объявлена как final).


class ParentClass
{
    const NAME = 'Parent';
}

class ChildClass extends ParentClass
{
    const NAME = 'Child';
}

echo ChildClass::NAME; // 'Child'

Типичная ошибка: попытка изменить константу после объявления или присвоить ей нескалярное выражение (например, результат вызова функции).


// Ошибка: Константу нельзя изменить
class MyClass
{
    const VALUE = 10;
}
MyClass::VALUE = 20; // Parse error: syntax error, unexpected '='

// Ошибка: нескалярное выражение
class MyClass
{
    const VALUE = time(); // Fatal error: Constant expression contains invalid operations
}

Для инициализации констант динамическими значениями используйте статическое свойство или метод, возвращающий значение.

Цели использования констант классов:

  • Хранение неизменяемых значений, связанных с классом (например, математические константы, статусы, настройки по умолчанию).
  • Создание именованных меток для избежания «магических чисел».
  • Обеспечение единого источника истины в рамках всей иерархии классов.

Как объявить константу в старых версиях PHP (до 7.1)?

До появления модификаторов доступа все константы были публичными. Альтернативой могло быть использование define внутри класса (но это не настоящая константа класса, а глобальная константа).


class MyClass
{
    // В PHP 5.x константы не могли быть protected или private
    const OLD_STYLE = 'legacy';
}

Проблема: глобальное пространство имен загрязняется, если использовать define. Рекомендуется всегда использовать const внутри класса.

Как использовать константы, объявленные в интерфейсе?

Интерфейсы могут содержать константы. Они всегда публичные и не могут быть переопределены в классах, реализующих интерфейс.


interface StatusInterface
{
    const ACTIVE = 1;
    const INACTIVE = 0;
}

class User implements StatusInterface
{
    public function getStatus()
    {
        return self::ACTIVE;
    }
}

echo User::ACTIVE; // 1

Ошибка: попытка переопределить константу интерфейса в классе-реализаторе приведет к фатальной ошибке.


class User implements StatusInterface
{
    const ACTIVE = 2; // Fatal error: Cannot inherit previously-inherited constant...
}

Как организовать константы в трейтах?

Трейты могут объявлять константы. Класс, использующий трейт, получает доступ к этим константам как к своим. Константы трейта могут быть переопределены в классе, если не помечены как final.


trait ConfigTrait
{
    public const TIMEOUT = 30;
}

class ApiClient
{
    use ConfigTrait;
    public const TIMEOUT = 60;
}

echo ApiClient::TIMEOUT; // 60

Если несколько трейтов или классов определяют одну и ту же константу, возникает конфликт. Решение – использовать псевдонимы.

Как создать константу, значение которой вычисляется во время выполнения?

Константы классов не могут содержать вызовы функций. Вместо этого можно использовать статическое свойство или статический метод, возвращающий значение.


class DynamicValue
{
    private static $cache = null;

    public static function getComputed()
    {
        if (self::$cache === null) {
            self::$cache = heavyComputation();
        }
        return self::$cache;
    }
}

echo DynamicValue::getComputed();

Для простых вычислений (например, математических) допускаются константные выражения, не использующие переменные.


class Circle
{
    const RADIUS = 10;
    const AREA = self::RADIUS * self::RADIUS * pi(); // НО: pi() – функция, нельзя
    // Правильно: const AREA = self::RADIUS * self::RADIUS * 3.14159;
}

Как использовать константы для эмуляции перечислений (enum)?

До появления нативных enum в PHP 8.1 константы классов часто использовались для создания перечислений.


class OrderStatus
{
    const PENDING = 0;
    const PROCESSING = 1;
    const COMPLETED = 2;
    const CANCELLED = 3;
}

С появлением enum такая практика устаревает, но для совместимости со старыми проектами продолжает использоваться.

Расширенные примеры работы с константами классов

Пример 1. Константы с модификаторами доступа и наследование

Пример

<?php
class Base
{
    public const PUBLIC_VAL = 100;
    protected const PROTECTED_VAL = 200;
    private const PRIVATE_VAL = 300;

    public function showProtected()
    {
        return self::PROTECTED_VAL;
    }
}

class Derived extends Base
{
    // Можно переопределить public и protected константы (если не final)
    public const PUBLIC_VAL = 150;
    protected const PROTECTED_VAL = 250;
    // private const недоступна для переопределения

    public function showPrivateFromParent()
    {
        // Нет доступа к PRIVATE_VAL родителя
        return 'cannot access';
    }
}

$obj = new Derived();
echo Derived::PUBLIC_VAL;        // 150 (переопределена)
echo Derived::PROTECTED_VAL;     // Ошибка доступа извне
echo $obj->showProtected();      // 250 (через метод экземпляра)
150
Deprecated: Access to protected constant...
250

Пример 2. Константы в трейтах и разрешение конфликтов

Пример

<?php
trait A
{
    public const VALUE = 1;
}

trait B
{
    public const VALUE = 2;
}

class MyClass
{
    use A, B {
        A::VALUE insteadof B;
        B::VALUE as B_VALUE;
    }
}

echo MyClass::VALUE;    // 1
echo MyClass::B_VALUE;  // 2
1
2

Пример 3. Магические константы класса (__CLASS__, __METHOD__ и т.п.)

Пример

<?php
class Magic
{
    public function showClass()
    {
        return __CLASS__;
    }

    public function showMethod()
    {
        return __METHOD__;
    }
}

$m = new Magic();
echo $m->showClass() . PHP_EOL;
echo $m->showMethod();
Magic
Magic::showMethod

Пример 4. Константы и статические свойства: сравнение

Пример

<?php
class Config
{
    // Константа: неизменяемое значение
    public const APP_NAME = 'MyApp';

    // Статическое свойство: может изменяться
    public static $version = '1.0.0';

    public static function updateVersion($newVersion)
    {
        self::$version = $newVersion;
    }
}

echo Config::APP_NAME;   // MyApp
echo Config::$version;   // 1.0.0
Config::updateVersion('2.0.0');
echo Config::$version;   // 2.0.0
// Config::APP_NAME = 'Other'; // Ошибка
MyApp1.0.0
2.0.0

Пример 5. Константы с использованием late static binding (self vs static)

Пример

<?php
class Base
{
    public const NAME = 'Base';

    public static function who()
    {
        return self::NAME;   // Всегда Base
    }

    public static function whoLate()
    {
        return static::NAME; // Зависит от вызывающего класса
    }
}

class Child extends Base
{
    public const NAME = 'Child';
}

echo Base::who();        // Base
echo Child::who();       // Base (self:: привязан к базовому классу)
echo Base::whoLate();    // Base
echo Child::whoLate();   // Child (static:: использует позднее статическое связывание)
BaseBaseBaseChild

Пример 6. Группы констант с помощью массивов (в PHP 8.0+)

Пример

<?php
class HttpStatus
{
    public const OK = 200;
    public const NOT_FOUND = 404;
    public const INTERNAL_ERROR = 500;

    public static function getCodes(): array
    {
        return [
            'OK' => self::OK,
            'NOT_FOUND' => self::NOT_FOUND,
            'INTERNAL_ERROR' => self::INTERNAL_ERROR,
        ];
    }
}

var_dump(HttpStatus::getCodes());
array(3) {
  ["OK"]=>
  int(200)
  ["NOT_FOUND"]=>
  int(404)
  ["INTERNAL_ERROR"]=>
  int(500)
}

Пример 7. Константы и итерация (ReflectionClass)

Пример

<?php
class Fruits
{
    const APPLE = 'apple';
    const BANANA = 'banana';
    const CHERRY = 'cherry';
}

$reflection = new ReflectionClass('Fruits');
$constants = $reflection->getConstants();
print_r($constants);
Array
(
    [APPLE] => apple
    [BANANA] => banana
    [CHERRY] => cherry
)

Пример 8. Использование const в контексте enum до PHP 8.1

Пример

<?php
class DayOfWeek
{
    const MONDAY = 1;
    const TUESDAY = 2;
    const WEDNESDAY = 3;
    const THURSDAY = 4;
    const FRIDAY = 5;
    const SATURDAY = 6;
    const SUNDAY = 7;

    public static function isWeekend(int $day): bool
    {
        return in_array($day, [self::SATURDAY, self::SUNDAY]);
    }
}

$day = DayOfWeek::SUNDAY;
echo DayOfWeek::isWeekend($day) ? 'Weekend' : 'Workday'; // Weekend
Weekend

Константы классов в PHP - comments

En
Php class constant (php)