define() или const в PHP: в чем разница и что лучше использовать для констант?
Основные различия между define() и const в PHP
Разница между этими двумя способами объявления констант действительно существенная, и выбор зависит от контекста использования. Давайте разберем все по порядку.
1. Время определения (compile time vs runtime)
Это ключевое отличие:
- const — определяется на этапе компиляции (compile time). Это значит, что константу нельзя объявить внутри условного оператора, цикла или функции. Она существует с момента загрузки файла.
- define() — выполняется во время выполнения (runtime). Поэтому define() можно использовать внутри циклов, условий, функций — где угодно.
// Работает
define('MY_CONST', 'value');
if (true) {
define('MY_OTHER_CONST', 'value2');
}
// Ошибка! const нельзя использовать внутри блока if
if (true) {
const MY_CONST = 'value'; // Parse error
}
2. Область видимости
const по умолчанию работает в пространстве имен (namespace), а define() — всегда в глобальном пространстве, если не указано иное.
namespace MyApp\Config;
// Эта константа будет MyApp\Config\DB_HOST
const DB_HOST = 'localhost';
// А эта всегда будет DB_PORT в глобальном пространстве
define('DB_PORT', 3306);
3. Использование в классах
const можно использовать внутри классов для объявления констант класса. define() — нет.
class User {
const MAX_AGE = 120;
public function getMaxAge() {
return self::MAX_AGE;
}
}
// Обращение
echo User::MAX_AGE; // 120
4. Типы данных
Оба могут хранить скалярные типы (int, float, string, bool) и null. Но:
- С PHP 5.6: const может хранить простые выражения (константы + операторы)
- С PHP 7.0: define() может хранить массивы
- С PHP 7.0: const может хранить массивы
// Оба работают с PHP 7+
define('COLORS', ['red', 'green', 'blue']);
const COLORS = ['red', 'green', 'blue'];
// Но const не может использовать сложные выражения
const SITE = 'http://' . $_SERVER['HTTP_HOST']; // Ошибка!
define('SITE', 'http://' . $_SERVER['HTTP_HOST']); // Работает
5. Производительность
const немного быстрее, потому что обрабатывается на этапе компиляции. Но разница настолько микроскопическая, что в реальных проектах ее можно не учитывать. Главное — читаемость и соответствие стандартам.
Что говорят PSR-1 и PSR-12?
Стандарты PSR-1 и PSR-12 рекомендуют использовать const для констант, не связанных с классами. Это сделано для единообразия кода и потому что const работает на уровне пространства имен, что лучше для автозагрузки и современных архитектур.
Рекомендация
Используйте const по умолчанию — это современный, предсказуемый и соответствующий стандартам способ. К define() обращайтесь только в особых случаях:
- Когда нужно объявить константу внутри условия или цикла
- Когда константа зависит от runtime-значения (например, из базы данных или $_SERVER)
- Для обратной совместимости со старым кодом
Пример правильного подхода в современном PHP:
namespace App\Config;
class Database {
const HOST = 'localhost';
const PORT = 3306;
const NAME = 'myapp';
}
// Для runtime-значений
if (getenv('APP_ENV') === 'development') {
define('DEBUG_MODE', true);
} else {
define('DEBUG_MODE', false);
}
<<Дополнительные нюансы: define() с регистронезависимостью и глобальные константы
В PHP существует еще один малоизвестный, но полезный аргумент для define() — третий параметр $case_insensitive. Он позволяет создавать регистронезависимые константы:
define('MY_CONST', 'value', true);
echo MY_CONST; // 'value'
echo my_const; // 'value' (тоже работает!)
Это может быть удобно для легаси-кода или при интеграции с системами, где регистр не фиксирован. Однако учтите:
- Этот параметр объявлен устаревшим с PHP 7.3 и будет удален в PHP 9.
- Регистронезависимые константы работают медленнее.
- const никогда не поддерживает регистронезависимость.
Еще один важный момент: define() всегда создает константу в глобальном пространстве имен, если вы явно не укажете неймспейс в имени. Это может привести к конфликтам имен:
namespace MyProject;
// Неожиданность: эта константа будет глобальной, а не в MyProject!
define('VERSION', '1.0');
// А это уже правильный способ для define с неймспейсом:
define(__NAMESPACE__ . '\VERSION', '1.0');
В то время как const автоматически привязывается к текущему пространству имен. Именно поэтому PSR рекомендует const — он менее подвержен ошибкам при работе с неймспейсами.
Итог: если вы пишете новый код на PHP 7.4+, используйте const. define() оставьте для специфических ситуаций, когда константа должна быть глобальной или зависеть от условий выполнения.