Увійти Реєстрація
Блог Серії
Кар'єра
Вакансії Компанії
Навчання
Документація Співбесіди Тестування Відео
Екосистема
Пакети Ресурси Проєкти Інструменти Події
Інше
Про нас Реклама

Чим const відрізняється від define і як константи класу замінюють магічні значення?

Два способи оголосити глобальну константу:

const MAX_UPLOAD_MB = 20;              // на етапі компіляції
define('MAX_UPLOAD_MB', 20);           // під час виконання, звичайна функція
const define()
коли визначається під час компіляції файлу під час виконання
усередині if, циклу, функції ні так
ім'я з виразу ні так: define("LIMIT_{$plan}", 10)
у класах і інтерфейсах так ні
простір імен враховує поточний namespace ім'я задається повністю рядком

На практиці в сучасному коді define() майже не потрібен: глобальні константи взагалі краще замінити конфігурацією чи константами класу.

Константи класу - значення, що належать класу й не змінюються:

final class Invoice
{
    public const int PAYMENT_TERM_DAYS = 14;
    protected const string NUMBER_PREFIX = 'INV-';

    public function dueDate(): CarbonImmutable
    {
        return $this->issued_at->addDays(self::PAYMENT_TERM_DAYS);
    }
}
  • видимість (public, protected, private) з PHP 7.1;
  • типізовані константи (const int) з PHP 8.3 - нащадок не може перевизначити константу значенням іншого типу;
  • final const (PHP 8.1) - заборонити перевизначення в нащадках;
  • static::CONST замість self::CONST - взяти значення з класу-нащадка (пізнє статичне зв'язування).

Магічні значення - числа й рядки без пояснення посеред коду:

if ($user->status === 3 && $order->total > 50000) { ... }   // що таке 3? чому 50000?

Замінювати їх варто так:

  • набір пов'язаних варіантів (статуси, типи, ролі) - enum, а не група констант: тип перевіряється, варіанти можна перебрати, у них можуть бути методи;
  • одиночне незмінне значення предметної області (термін оплати, максимальна довжина) - константа класу, де воно використовується;
  • значення, що відрізняється між середовищами чи може змінитися без деплою (ліміти, ключі, адреси) - конфігурація (config('billing.limit')), а не константа.

Константи в інтерфейсах допустимі, але вони потрапляють у кожен клас, що реалізує інтерфейс. Інтерфейс описує поведінку, тож набір значень для нього - ознака, що потрібен enum.

Динамічний доступ: constant(Invoice::class . '::PAYMENT_TERM_DAYS') чи з PHP 8.3 Invoice::{$name} - корисно в рідкісних випадках, але ламає пошук використань в IDE.

Докладніше в документації: Константи класу

57

Схожі питання