Константы в 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
, object
, resource и т.д. не являются скалярными.
// скаляры 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
#5 const зависит от пространства имен, а define нет
Если мы создаем константу в namespace, то:
- При использовании const - константа будет находится в этом пространстве и не будет доступна вне его.
- При использовании define - константа регистрируется как глобальная и будет доступна за пределами namespace.
namespace My\Space; const FOO = 'bar'; define( 'FOOO', 'baz' );
Теперь чтобы обратиться к этим константам за пределами пространства имен, например из другого файла, нужно писать так:
echo \My\Space\FOO; // bar echo FOOO; // baz
Итог сравнения
Определять константу почти всегда лучше с помощью define(), потому что тут больше возможностей и меньше вариантов «поймать» ошибку. Исключения:
- У вас версия PHP 5.6 и вам нужно сохранить массив в константу, тут поможет const.
- Вам нужно, чтобы константа была не в глобальной видимости, а в видимости пространства имен (namespace).
Константы 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;
До PHP 7.1 постоянные класса всегда общедоступны - нет статуса private или protected. Однако с версии PHP 7.1 константам класса можно указать модификатор:
class Foo { // Начиная с PHP 7.1.0 public const BAR = 'bar'; private const BAZ = 'baz'; }
Константы для классов чем-то похожи на static свойства класса. Не углубляясь в подробности, разница в том, что константу нельзя изменить.
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. Полное имя класса (с указанием пространства имен). |