php Разница между define и const для объявления констант

Решил вот заполнить пробел в знаниях и заодно сделать доброе дело и перевести вот этот пост (а если быть точнее, то лучший ответ на него) о различиях между объявлениями констант в PHP на русский. Если у кого-то будут замечания по переводу, пожалуйста указывайте на них, так как я далеко не переводчик ))

Фундаментальная разница между ними (const и define) состоит в том, что const объявляет константы во время компиляции, в то время как define объявляет их во время выполнения скрипта. Этот факт определяет большинство недостатков конструкции const. Вот некоторые из них:

  • const не может быть использована для динамически объявляемых констант. Чтобы объявить глобальную константу, она должна быть применена на самом внешнем уровне:
    if (...) {
        const FOO = 'BAR';    // Неверно
    }
    // но
    if (...) {
        define('FOO', 'BAR'); // Верно
    }

    Зачем нам в принципе может понадобится такое делать? Одно часто используемое применение состоит в том, чтобы проверять объявлена ли константа или еще нет:

    if (!defined('FOO')) {
        define('FOO', 'BAR');
    }
  • const принимает только статические значения (число, строку или другие постоянные величины, такие как правда, ложь, null, __FILE__), в то время как define() может принимать любые выражения. Начиная с PHP 5.6 выражения в качестве констант доступны также и в const:
    const BIT_5 = 1 << 5;    // Верно начиная с PHP 5.6, до этой версии неверно 
    define('BIT_5', 1 << 5); // Всегда верно
  • const может быть присвоено только чётко определенное имя, в то же время define() принимает любое выражение в качестве имени. Этот факт позволяет делать вещи наподобие таких:
    for ($i = 0; $i < 32; ++$i) {
        define('BIT_' . $i, 1 << $i);
    }
  • const всегда чувствительна к регистру, тогда как define() позволяет задавать нечувствительность к регистру, путем передачи значения "true" третьим параметром:
    define('FOO', 'BAR', true);
    echo FOO; // BAR
    echo foo; // BAR

Это была негативная "сторона медали". Теперь давайте посмотрим на причины, по которым лично я всегда использую const, если не возникает ни одной из вышеперечисленных ситуаций:

  • const просто легче читается. Это языковая конструкция а не функция, а также она совпадает с тем, как мы объявляем константы в классах.
  • const объявляет константу в соответствующем пространстве имен, тогда как в define() нужно передавать полное название пространства имен:
    namespace A\B\C;
    // Определение константы A\B\C\FOO:
    const FOO = 'BAR';
    define('A\B\C\FOO', 'BAR');
  • Начиная с PHP 5.6 константы, объявленные при помощи сonst могут быть массивами, в то время как define() пока не поддерживает массивов. Хотя в PHP7 массивы будут поддерживаться обоими типами объявлений
    const FOO = [1, 2, 3];    // Верно для PHP 5.6
    define('FOO', [1, 2, 3]); // Неверно для PHP 5.6, верно для PHP 7.0
  • Так как const это языковая конструкция и инициализируется она на этапе компиляции, такие константы несколько быстрее чем константы типа define().

    Хорошо известно, что define()ы медлительны, если используется большое количество констант. Люди даже изобрели такие вещи как apc_load_constants() и hidef чтобы обойти этот недостаток

    const инициализирует константы приблизительно в два раза быстрее (На машинах для разработки с включённым XDebug даже больше). С другой стороны, время поиска не меняется (поскольку оба типа констант делят одну таблицу поиска )

Наконец, стоит отметить, что const также используется внутри класса или интерфейса, для объявления классовой константы или константы интерфейса. define() не может быть использована в подобных целях:

class Foo {
    const BAR = 2; // valid
}
// but
class Baz {
    define('QUX', 2); // invalid
}

Подытоживая:
За исключением случаев динамического объявления или же объявления в виде выражения, используйте const вместо define() просто по причине лучшей читаемости!

Key Words for FKN + antitotal forum (CS VSU):

vedro-compota's picture

отлично, сюда можно сослать из заметки о константах.

_____________
матфак вгу и остальная классика =)

melisa's picture

из констант сослалась

Voronve's picture

Спасибо за отзыв! )