define() vs const в PHP: битва титанов объявления констант
Вы когда-нибудь задумывались, почему в PHP есть целых два способа объявить константу? Казалось бы, зачем плодить сущности? Но дьявол, как всегда, кроется в деталях. Этот вопрос на Stack Overflow собрал тысячи просмотров, и неспроста — разница между define() и const может серьёзно повлиять на архитектуру вашего кода.
Сегодня мы раз и навсегда разберёмся, что к чему. Вы узнаете не только синтаксические отличия, но и когда какой инструмент даёт реальное преимущество. Поехали!
Краткий экскурс: что такое константа в PHP?
Константа — это идентификатор для простого значения. Её главная фишка: значение не может быть изменено во время выполнения скрипта (в отличие от переменной). По умолчанию константы чувствительны к регистру, но это можно настроить (спойлер: с define()).
Пример классической константы:
<?php
define("MAX_UPLOAD_SIZE", 10485760); // 10 MB в байтах
echo MAX_UPLOAD_SIZE; // 10485760
?>
То же самое, но с const:
<?php
const MAX_UPLOAD_SIZE = 10485760;
echo MAX_UPLOAD_SIZE;
?>
Вроде бы одинаково. Но копнём глубже.
Главные отличия define() от const
Давайте разложим всё по полочкам. Вот ключевые различия, которые нужно знать каждому PHP-разработчику.
1. Время объявления: компиляция vs выполнение
Это самое фундаментальное отличие.
const— объявляется на этапе компиляции. Это значит, что вы не можете использоватьconstвнутри циклов, условий или функций. Он должен быть объявлен в «теле» класса (для констант классов) или в глобальной области видимости.define()— выполняется в рантайме. Вы можете поместить его куда угодно: внутрьif,for,while, даже в функцию (хотя это плохая практика).
Пример, который не сработает с const:
<?php
if (PHP_OS === 'WINNT') {
const PLATFORM = 'Windows';
// Fatal error: Cannot use const in control structure
}
?>
А с define() — пожалуйста:
<?php
if (PHP_OS === 'WINNT') {
define('PLATFORM', 'Windows');
echo PLATFORM; // Windows
}
?>
2. Типы данных: массивы и объекты
Долгое время define() поддерживал только скалярные типы (строки, числа, булевы значения). Начиная с PHP 7, define() научился работать с массивами.
const тоже поддерживает массивы (начиная с PHP 5.6), но не поддерживает объекты или выражения:
<?php
// Работает с PHP 7+
define('FRUITS', ['apple', 'banana', 'cherry']);
echo FRUITS[1]; // banana
// Тоже работает (PHP 5.6+)
const COLORS = ['red', 'green', 'blue'];
// А вот так — ошибка!
// const RESULT = 2 + 3; // Работает, это константное выражение
// const DYNAMIC = rand(1, 10); // Ошибка! Не константное выражение
?>
Важно: define() может использовать результат функций (define('SITE_NAME', get_site_name())), а const — только константные выражения (числа, строки, другие константы).
3. Пространство имён и область видимости
Тут есть тонкий, но важный нюанс.
define()— всегда создаёт глобальную константу. Даже если вы вызываете его внутри пространства имён, константа будет доступна отовсюду.const— подчиняется правилам пространства имён. Константа, объявленная в неймспейсеMyApp\Config, будет называтьсяMyApp\Config\DB_HOST.
Пример:
<?php
namespace MyApp\Config;
// define — глобальная
define('GLOBAL_DB', 'localhost');
// const — в неймспейсе
const LOCAL_DB = '127.0.0.1';
// Где-то в другом файле:
echo \GLOBAL_DB; // localhost
echo \MyApp\Config\LOCAL_DB; // 127.0.0.1
?>
4. Чувствительность к регистру
define() принимает третий необязательный параметр case_insensitive (до PHP 7.3). Если передать true, константу можно будет вызывать без учёта регистра. В PHP 8.0 этот параметр удалён.
<?php
// До PHP 7.3
define('SITE', 'PythonLib', true);
echo site; // PythonLib (работало)
?>
const — всегда чувствителен к регистру. SITE и site — разные вещи.
5. Константы классов
Это отдельная песня. Внутри классов можно использовать только const. define() там не работает.
<?php
class Database {
const HOST = 'localhost';
const PORT = 3306;
// Так нельзя:
// define('DB_NAME', 'test'); // Ошибка!
}
?>
Производительность: кто быстрее?
Короткий ответ: разница незначительна, но const чуть быстрее при чтении.
const— объявляется на этапе компиляции, поэтому доступ к нему — это просто подстановка значения.define()— требует вызова функции при объявлении, хотя после объявления разница в скорости доступа минимальна.
В реальных проектах вы не заметите разницы, если не объявляете миллионы констант. Но если вы перфекционист — используйте const для статических значений.
Когда что использовать? Практические рекомендации
Давайте сведём всё в чёткие правила.
Используйте const, если:
- Вы объявляете константу внутри класса (это единственный вариант).
- Значение известно на этапе написания кода (например,
PI = 3.14). - Вы хотите чётко следовать правилам пространства имён.