Два способи оголосити глобальну константу:
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.