Константи в PHP – const і define()
У цій замітці розберемося, у чому різниця в оголошенні PHP констант за допомогою ключового слова const та функції define() .
Константи в PHP – це «постійні», значення яких вказується лише один раз і потім не може бути змінено. При спробі змінити значення воно не зміниться і з’явиться PHP замітка: «Constant already defined» (константа вже визначена):
define('FOO', 'val'); define('FOO', 'val2'); // Notice: Constant already defined echo FOO; //> val
Оголошувати константи в PHP можна двома способами:
// 1 define( 'NAME', 'VALUE' ); // 2 const NAME = 'VALUE';
Кожен спосіб має свої особливості, щоб їх зрозуміти, давайте розглянемо все поетапно, як і що змінювалося з кожною версією PHP.
Як створювати константи
PHP менше 5.3
До 5.3 PHP, константи можна було визначати тільки через define() . Ключове слово const з’явилося із версії 5.3.
Константи можуть зберігати лише скаляри . Скалярні змінні – це змінні з типами integer , float , string і boolean . Типи array , об’єкт і ресурс не є скалярними.
// скаляри define( 'FOO', 10); define( 'FOO', 10.9); define( 'FOO', 'val' ); define( 'FOO', true ); // не скаляри define( 'FOO', array(1) ); // константа не встановиться і отримаємо Warning define( 'FOO', (object) array(1) ); // константа не встановиться і отримаємо Warning
З версії PHP 5.3
З’явилося ключове слово const , і тепер константу можна визначати ще й за допомогою нього.
Однак, у const не можна вказати змінну, функцію або якийсь вираз, а потрібно передавати скаляр «безпосередньо»:
const FOO = 'val'; // Немає помилок const FOO = $ var; // Parse error const FOO = home_url (); // Parse error const FOO = 5+10; // Parse error const FOO = 'foo'.'bar'; // Parse error
Тоді як для define() таких обмежень немає.
define('FOO', 'val'); // Немає помилок define('FOO', $var); // Немає помилок define('FOO', home_url() ); // Немає помилок define('FOO', 5 + 10); // Немає помилок define('FOO', 'foo'.'bar'); // Немає помилок
PHP 5.6
Стало можливим вказувати значення const примітивні PHP вирази (вирази з скалярів):
const FOO = 1+2; const FOO = 'foo'. 'bar';
Стало можливим зберігати масиви у константах:
const FOO = [1, 2, 3]; // працює define( 'FOO', [1, 2, 3]); // не працює в PHP 5.6, працює в PHP 7.0
Різниця між define() та const
#1 const повинні бути оголошені у верхній області
Тому що вони визначаються під час компілювання скрипту. Це означає, що const не можна використовувати всередині функций/циклов/выражений if
чи try/catch
блоків.
if ( 1 ) { const NAME = 'VALUE'; // не працює } // але if ( 1 ) { define('NAME', 'VALUE'); // працює }
#2 const завжди реєстрозалежна
У той час як define() дозволяє створити регістро-незалежні константи:
define( 'NAME', 'VALUE', true ); echo NAME; // VALUE echo name; // VALUE
#3 const розуміє лише скаляри
const не можна передати змінні, функції, вирази, а define() можна:
const FOO = $ var; // Parse error const FOO = home_url (); // Parse error define('FOO', $var); // Немає помилок define('FOO', home_url() ); // Немає помилок
З версії PHP 5.6 const також можна вказувати примітивні вирази, а не тільки скаляри.
#4 const може зберігати масиви з версії PHP 5.6, а define з PHP 7.0
const FOO = [1, 2, 3]; // працює з PHP 5.6 define( 'FOO', [1, 2, 3]); // працює з PHP 7.0
Підсумки порівняння
Визначати константу майже завжди краще за допомогою define() , тому що тут більше можливостей та менше варіантів «зловити» помилку. Виняток це коли у вас версія PHP 5.6 і вам потрібно зберегти масив в константу, тут допоможе const .
#5 const залежить від простору імен, а define ні
Якщо ми створюємо константу в namespace, то:
- При використанні const – константа буде знаходитись у цьому просторі і не буде доступна поза ним.
- При використанні define – константа реєструється як глобальна і доступна за межами namespace.
namespace MySpace; const FOO = 'bar'; define( 'FOOO', 'baz' );
Тепер, щоб звернутися до цих константів за межами простору імен, наприклад, з іншого файлу, потрібно писати так:
echo My Space FOO; // bar echo FOOO; // baz
Константи PHP класу
Оголошуються лише за допомогою const . Правила для них такі як описано вище: приймають тільки скаляри, не розуміють PHP змінні, функції, вирази…
Оголошена константа належить саме класу, вона належить жодному об’єкту і є спільної всіх об’єктів (примірників) класу.
class My_Class { const NAME = 'VALUE'; // починаючи з PHP 5.6 можна використовувати математичні вирази const SEC_PER_DAY = 60*60*24; function print_name() { // Звернення до константи класу всередині методу через self (сам клас) echo self::NAME; } } // звернення до константи поза класом // можна викликати із глобальної області видимості без ініціалізації екземпляра класу echo My_Class::NAME;
Постійні класи завжди загальнодоступні – немає статусу private чи protected . Однак з версії PHP 7.1 константам класу можна вказати модифікатор:
class Foo { // Починаючи з PHP 7.1.0 public const BAR = 'bar'; private const BAZ = 'baz'; }
Константи для класів чимось схожі на статичні властивості класу. Не заглиблюючись у подробиці, різниця у цьому, що константу не можна змінити.
class My_Class { const NAME = 'VALUE'; static $name = 'VALUE'; } echo My_Class::NAME; echo My_Class::$name;
«Чарівні» константи
І на завершення згадаємо про особливі константи PHP…
У PHP є дев’ять магічних констант, які змінюють своє значення залежно від контексту, в якому вони використовуються. Наприклад, значення __LINE__ залежить від рядка в скрипті, де ця константа вказана. Усі “чарівні” константи дозволяються під час компіляції, на відміну від звичайних констант, які дозволяються під час виконання. Спеціальні константи нечутливі до регістру та їх список наведений нижче:
Константа | Опис |
---|---|
__LINE__ | Поточний номер рядка у файлі. |
__FILE__ | Повний шлях та ім’я поточного файлу, у якому викликається константа. |
__DIR__ | PHP 5.3.0. Директорія файлу, де використовується константа. Те саме що dirname(__FILE__) . Не має слеша наприкінці, крім кореневої директорії. |
__FUNCTION__ | Ім’я функції. |
__CLASS__ | Назва класу. Це ім’я містить назву простору імен, в якому клас був оголошений (наприклад, Foo Bar). Також працює у трейтах. При використанні методів трейтів є ім’ям класу, у якому ці методи використовується. |
__TRAIT__ | PHP 5.4.0. Ім’я Трейт. Це ім’я містить назву простору імен, в якому трейт був оголошений (наприклад, Foo Bar). |
__METHOD__ | Ім’я методу класу. |
__NAMESPACE__ | PHP 5.3.0. Назва поточного простору імен. |
ClassName::class | PHP 5.5.0. Повне ім’я класу (із зазначенням простору імен). Також дивіться :: class. |