Константи в 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. | 
