Константи в 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::classPHP 5.5.0. Повне ім’я класу (із зазначенням простору імен). Також дивіться :: class.

Залишити коментар

Ваша e-mail адреса не оприлюднюватиметься. Обов’язкові поля позначені *