Александр Некрасов · Автономное руководство

PHP: полный мануал с примерами, функциями и ООП

Разделы этой страницы
  1. Константы: одно имя для неизменного правила
  2. Первое действие: объявить правило и прочитать его
  3. Подписать две цены одним правилом
  4. Разбираем const PAGE_SIZE = 3 по частям
  5. Понятное имя без $ и единица измерения
  6. Изменяемые данные и неизменное правило
  7. Начальное значение из других правил
  8. define: значение сначала получили, затем объявили
  9. Зачем давать правилу отдельное имя
  10. Минимальная программа: два списка, одно правило
  11. От числа страниц к содержимому каждой страницы
  12. const и define внутри реального сценария
  13. Специальные имена: где находится этот код
  14. Проверить наличие и обнаружить опечатку
  15. Константа-массив и отдельный рабочий список
  16. Чтение в функции без global
  17. Полное имя и namespace
  18. Два модуля строят свои пути без конфликта имён
  19. Имена, уже определённые PHP
  20. Специальные имена показывают место исходного кода
  21. Константа с объектом не даёт глубокой неизменяемости
  22. PHP 8.5: приведения, Closure и first-class callable
  23. Выбрать инструмент по задаче
  24. Проверьте выбор: правило или изменяемые данные
  25. Функции и методы этой темы
  26. Код и руководство с собой
PHP 8.5.11149 глав4458 карточек справочника
Дерево руководства

Глава 9 · С нуля

Константы: одно имя для неизменного правила

От объявления и чтения правила до const/define, пространства имён, специальных имён, массивов и версионных особенностей. Четыре подробные карточки функций.

Первое действие: объявить правило и прочитать его

Наглядная модель

Одно правило читают два расчёта

Размер страницы объявлен один раз. Количество записей отличается, а правило для обеих страниц одинаковое.

  • PAGE_SIZE = 3

    Имя константы ведёт к неизменному значению 3.

    • Каталог: 7 записей

      Расчёт читает PAGE_SIZE и получает 3 страницы.

    • Архив: 4 записи

      Тот же размер страницы даёт 2 страницы.

Две подписи ниже показывают потребителей одного правила, а не ссылки PHP через &. Размер и количество записей — разные данные.

Рядом с ценами магазина нужно показывать обозначение валюты. Чтобы не перепечатывать его в каждом месте, дадим значению одно имя. Константа похожа на подписанное правило: имя связано с одним значением в текущем выполнении программы. Это не запись в базе и не настройка, которая сама сохранится после остановки PHP.

От объявления к выводу
  1. const SHOP_CURRENCY = 'RUB'; — связываем имя со строкой
  2. echo SHOP_CURRENCY; — читаем значение
  3. В вывод попадают три буквы RUB

const начинает объявление; SHOP_CURRENCY — выбранное имя без знака $; = связывает его с начальным значением; кавычки ограничивают текст, а ; завершает инструкцию. echo отправляет прочитанное значение в вывод. Тег <?php начинает участок PHP-кода.

Самый маленький пример константыСамостоятельный пример
<?php
const SHOP_CURRENCY = 'RUB';
echo SHOP_CURRENCY;
Ожидаемый результат
RUB

Имя после echo записано без кавычек: PHP находит связанную с ним строку. Запись echo 'SHOP_CURRENCY' напечатала бы название, а не RUB. Сохраните пример как example.php и выполните php example.php.

Попробуйте. Поменяйте валюту на EUR, оставив echo прежним.

Разбор

Измените значение в объявлении и запустите файл снова. Это изменение исходника до следующего запуска, а не переназначение константы внутри уже работающего скрипта.

Подписать две цены одним правилом

Теперь обозначение валюты участвует в двух ценниках. Значения цен различаются; правило подписи одно. Запятые в echo выводят части по очереди, пробел внутри кавычек отделяет число от обозначения. В примере цены заранее заданы целыми рублями.

Прочитать константу рядом с меняющимися ценамиСамостоятельный пример
<?php
const SHOP_CURRENCY = 'RUB';
$teaPrice = 150;
$cupPrice = 200;
echo 'Чай: ', $teaPrice, ' ', SHOP_CURRENCY, "\n";
echo 'Чашка: ', $cupPrice, ' ', SHOP_CURRENCY, "\n";
Ожидаемый результат
Чай: 150 RUB
Чашка: 200 RUB

Первый echo читает 150 и RUB, второй — 200 и то же RUB. Изменение объявления перед новым запуском изменит обе подписи. Переменная teaPrice по-прежнему может меняться в ходе расчёта. Замена RUB на EUR здесь меняет только надпись: пересчёта валют программа не делает.

Имя читается в двух местах
  1. SHOP_CURRENCY хранит RUB.
  2. teaPrice=150 → «Чай: 150 RUB».
  3. cupPrice=200 → «Чашка: 200 RUB».

Попробуйте добавить стоимость тарелки 300 тем же способом. Получится «Тарелка: 300 RUB». Для денег с копейками сначала задайте единицы и правило форматирования; константа сама этого не решает.

Разбираем const PAGE_SIZE = 3 по частям

const PAGE_SIZE = 3;
echo PAGE_SIZE;
Часть записиЧто она означает
constОбъявить константу в этой области имён. Здесь объявление находится на верхнем уровне файла.
PAGE_SIZEНаше имя правила. Знака $ нет; верхний регистр — договорённость об оформлении.
= 3Значение при объявлении. Это не разрешение присваивать константе новые значения позже.
;Конец инструкции.
PAGE_SIZE в echoПрочитать значение. Строка "PAGE_SIZE" напечатала бы само имя.

Объявите правило до места его использования. Для другого количества записей нужна переменная, для фиксированного размера страницы подходит константа. Названия чувствительны к регистру. Неизвестное имя в PHP 8 вызывает Error; кавычки вокруг ключей массива от этого не становятся необязательными.

Понятное имя без $ и единица измерения

Обычное переносимое имя начинайте с буквы A–Z/a–z или подчёркивания; дальше допустимы также цифры. Пробелы и дефисы не подходят для обычного обращения. PHP допускает некоторые дополнительные байты в идентификаторах, но это не проверка правильности Unicode-слова. Для общего проекта проще согласовать ASCII-имена. Верхний регистр — соглашение, а не требование языка.

ЗаписьКак её читать
DELIVERY_PRICE_KOPECKSНазначение и единица: 29900 нельзя принять за рубли.
PAGE_SIZEПравило размера страницы.
2_PAGES / page-sizeНе обычные допустимые имена: цифра в начале или дефис.
__CUSTOM__Не занимайте форму имён, зарезервированную для специальных возможностей.
Регистр различает именаСамостоятельный пример
<?php
const DELIVERY_LIMIT = 3;
const delivery_limit = 7;
echo DELIVERY_LIMIT, "\n";
echo delivery_limit, "\n";
Ожидаемый результат
3
7

Это две разные константы. В рабочем коде такая пара неудобна: выбирайте содержательно разные имена. Встроенные true, false и null имеют особые правила; не выводите из них правило для пользовательских имён. Запятые в echo выводят части по очереди, "\n" означает перевод строки.

Изменяемые данные и неизменное правило

Текущий номер страницы меняется, размер страницы обычно задан настройкой. Переменная хранит меняющееся значение; константа выражает правило. Слово «глобальная» не делает переменную константой.

Первая и вторая страница каталогаСамостоятельный пример
<?php
const PAGE_SIZE = 12;
$page = 1;
echo $page, ': ', PAGE_SIZE, "\n";
$page = 2;
echo $page, ': ', PAGE_SIZE, "\n";
Ожидаемый результат
1: 12
2: 12

Присваивание меняет page, оба чтения PAGE_SIZE дают 12. У константы нет обычного переназначения через = и удаления через unset. Для следующей страницы меняется переменная, а не правило размера.

Знак $ выбирает другое имяСамостоятельный пример
<?php
const LIMIT = 12;
$LIMIT = 5;
echo LIMIT, "\n";
echo $LIMIT, "\n";
Ожидаемый результат
12
5

Переменная $LIMIT не заменяет константу LIMIT. Технически допустимо, но лучше назвать её $requestedCount, чтобы различие было видно по смыслу.

Начальное значение из других правил

Правило задано в минутах, а операция принимает секунды. Сохраним обе единицы под ясными именами. Знак * умножает числа. В const допустимы константные выражения — особый набор разрешённых операций. Обычное чтение переменной и произвольный вызов вроде getenv сюда не подходят; набор возможностей расширяется с версиями.

Перевести минуты в секундыСамостоятельный пример
<?php
const MINUTES_PER_RUN = 5;
const SECONDS_PER_MINUTE = 60;
const RUN_TIMEOUT_SECONDS = MINUTES_PER_RUN * SECONDS_PER_MINUTE;
echo RUN_TIMEOUT_SECONDS;
Ожидаемый результат
300

Вычисляется произведение, после чего читается значение правила. Скрипт от этого сам не остановится через 300 секунд: число ещё нужно передать инструменту, который ограничивает операцию.

Обычные значения констант — числа, строки, bool, null и массивы. Современный PHP допускает также объекты в определённых объявлениях; ниже показаны условия. Ресурс открытого файла не используйте как глобальное правило: у него меняющееся время жизни. Выбирайте const/define по происхождению значения, а не по обещанию микроскопического ускорения.

define: значение сначала получили, затем объявили

define — встроенная функция. Круглые скобки содержат аргументы: первый — строковое имя, второй — значение. Запятая их разделяет. Она подходит, когда настройка вычисляется во время работы.

Объявить уже полученную настройкуСамостоятельный пример
<?php
$configuredPageSize = 15;
define('CONFIGURED_PAGE_SIZE', $configuredPageSize);
echo CONFIGURED_PAGE_SIZE;
Ожидаемый результат
15

Имя в кавычках нужно для аргумента define; чтение результата опять записано без кавычек. Настройка здесь заведомо корректна. Внешний ввод сначала нужно проверить, поскольку define не знает допустимый размер страницы.

ПотребностьПодход
Правило буквально записано в исходникеconst NAME = значение;
Значение вычислено по даннымdefine('NAME', $checkedValue);
Два клиента требуют разных настроек одновременноМассивы конфигурации или отдельные объекты.
Значение меняется по ходу сценарияПеременная.

Зачем давать правилу отдельное имя

В каталоге и архиве нужно показывать одинаковое число карточек. Если написать 3 в двух местах, при изменении одного места страницы начнут вести себя по-разному. Назовём правило PAGE_SIZE и будем читать его в обоих расчётах. Константа — имя значения, которое после объявления нельзя переназначить в этом выполнении программы.

Результат главы: вы объявите правило, прочитаете его в функции и построите путь к файлу через __DIR__. Для следующей ступени понадобятся функции; первая программа выше уже работает без них.

Каждый пример запускается отдельно. Скачайте его архив, распакуйте целиком, откройте терминал в этом каталоге и выполните php example.php. Сравните вывод с блоком «Ожидаемый результат». Не объединяйте примеры в один файл: некоторые намеренно повторяют имена функций и классов.

Минимальная программа: два списка, одно правило

Здесь результат — нужное число страниц, которое затем можно использовать в навигации. При семи товарах и размере 3 страницы содержат 3, 3 и 1 товар. Вызов intdiv(9, 3) получает два целых аргумента и возвращает частное 3 без дроби; echo сразу печатает этот возврат. Прибавление размера минус один позволяет учесть неполную последнюю страницу: 7 + 3 − 1 = 9, затем 9 / 3 = 3. Для четырёх записей 4 + 3 − 1 = 6, затем 6 / 3 = 2. Это формула для неотрицательного количества и положительного размера.

Один размер страницы для двух списковСамостоятельный пример
<?php
declare(strict_types=1);

const PAGE_SIZE = 3;

$catalogCount = 7;
$archiveCount = 4;
echo 'Каталог: ', intdiv($catalogCount + PAGE_SIZE - 1, PAGE_SIZE), " страницы\n";
echo 'Архив: ', intdiv($archiveCount + PAGE_SIZE - 1, PAGE_SIZE), " страницы\n";
Ожидаемый результат
Каталог: 3 страницы
Архив: 2 страницы

Оба расчёта читают одно PAGE_SIZE. Число записей меняется, правило размера страницы — нет. intdiv делит целые числа без дробной части; прибавление PAGE_SIZE − 1 округляет число страниц вверх. Поменяйте PAGE_SIZE на 4: каталог даст 2, архив — 1. Здесь размеры известны и положительны.

От числа страниц к содержимому каждой страницы

Один расчёт числа страниц ещё не выбирает товары. Следующая ступень использует обычный массив и foreach: список хранит названия, array_chunk возвращает массив страниц, а каждый внутренний массив содержит не более PAGE_SIZE названий. Первый foreach получает номер и страницу, второй читает товары этой страницы. Нумерация массива начинается с 0, человеку показываем номер плюс один.

Показать все товары на трёх страницахСамостоятельный пример
<?php
const PAGE_SIZE = 3;
$products = ['Чай', 'Кофе', 'Кружка', 'Тарелка', 'Ложка', 'Сахар', 'Мёд'];
$pages = array_chunk($products, PAGE_SIZE);
foreach ($pages as $index => $items) {
    echo 'Страница ', $index + 1, ":\n";
    foreach ($items as $title) {
        echo '- ', $title, "\n";
    }
}
Ожидаемый результат
Страница 1:
- Чай
- Кофе
- Кружка
Страница 2:
- Тарелка
- Ложка
- Сахар
Страница 3:
- Мёд

Array_chunk получает семь названий и размер 3; возвращает три вложенных списка. Внешний foreach последовательно получает items из трёх, трёх и одного названия. Каждый внутренний echo читает реальный товар. При PAGE_SIZE=4 получатся страницы из четырёх и трёх товаров. Пустой products даёт пустой pages: цикл ничего не выводит. Здесь весь список уже в памяти; большие выборки из базы обычно ограничивают на стороне запроса.

Параметры и сохранение исходных ключей подробно разобраны у array_chunk. Это вывод в терминал; HTML-ссылки и чтение выбранного номера страницы относятся к следующему веб-проекту.

const и define внутри реального сценария

Этот объединённый пример выполняйте после параметров и return и try/catch. Сначала инициализация выбирает формат; затем функция получает число строк и возвращает текстовый план. JSON здесь пока только название формата, декодирование или создание файла не используется.

const подходит для заранее записанного правила. В обычном файле его объявление не помещают внутрь if или функции. define — вызов функции; он может выполняться после условия и проверки полученной настройки. Имя передают строкой, вторым аргументом — значение. Для этого вводим ещё две записи: defined("ИМЯ") возвращает bool, а !defined(...) означает «ещё не объявлено».

Функция экспорта читает правило и проверенную настройкуСамостоятельный пример
<?php
declare(strict_types=1);

const EXPORT_PAGE_SIZE = 3;

// Учебное значение. В приложении настройку сначала читают и проверяют.
$configuredFormat = 'json';
if (!in_array($configuredFormat, ['json', 'csv'], true)) {
    throw new InvalidArgumentException('Неподдерживаемый формат');
}
if (!defined('BRIDGE_EXPORT_FORMAT')) {
    define('BRIDGE_EXPORT_FORMAT', $configuredFormat);
}

function exportPlan(int $itemCount): string
{
    if ($itemCount < 0) {
        throw new InvalidArgumentException('Отрицательное число записей');
    }
    $pages = intdiv($itemCount + EXPORT_PAGE_SIZE - 1, EXPORT_PAGE_SIZE);
    return BRIDGE_EXPORT_FORMAT . ': ' . $pages . ' страниц';
}

echo exportPlan(7), "\n";
echo exportPlan(0), "\n";
try {
    exportPlan(-1);
} catch (InvalidArgumentException) {
    echo "Неверное количество отклонено\n";
}
Ожидаемый результат
json: 3 страниц
json: 0 страниц
Неверное количество отклонено

defined получает имя строкой и проверяет существование; define объявляет значение во время выполнения. Функция читает уже объявленные константы без global. Это только план: ни JSON-файл, ни сетевой запрос здесь не создаются. Проверка defined полезна для необязательной настройки, но не должна скрывать конфликт двух разных конфигураций.

Константа не обновляет настройки между HTTP-запросами и не заменяет хранилище. Если разным клиентам нужны разные лимиты, передайте лимит аргументом или настройкой объекта. Глобальная константа с одним значением не выразит два разных режима одновременно. Константы класса вида Product::TYPE разобраны рядом с классами.

Внутри namespace строки для define и defined не дополняются пространством имён автоматически. Для именованной константы передают полное строковое имя, например Bridge\Catalog\PAGE_SIZE. Псевдонимы use также не применяются к таким строкам.

Место / входДействие и точный результат
in_array($configuredFormat, ['json', 'csv'], true)Получает строку json и разрешённый список; строгая проверка возвращает true. Отрицание ! даёт false, исключение не выбрасывается.
defined('BRIDGE_EXPORT_FORMAT')В самостоятельном файле имя ещё отсутствует: false. ! делает условие истинным, define объявляет json.
exportPlan(7)Локальный itemCount=7. Проверка отрицательного числа не срабатывает. intdiv(7+3−1,3) возвращает 3 в pages. Return возвращает строку json: 3 страниц прямо в echo.
exportPlan(0)Новый локальный itemCount=0; intdiv(2,3) даёт 0. Return возвращает json: 0 страниц; это план пустого набора.
exportPlan(-1)itemCount=-1; throw прерывает вызов, строки из return нет. Catch выбирает сообщение об отклонении.
Дальнейшее применениеСохраните $message = exportPlan(7); затем echo $message. Для фактического разбиения списка выше показан array_chunk; текстовый план сам не экспортирует данные.

Специальные имена: где находится этот код

PHP подставляет в специальные имена сведения о месте кода. __DIR__ — каталог исходника, __FILE__ — его полный путь, __LINE__ — строка, __FUNCTION__ — имя функции. Это не ваши настройки. Они не объявляются через define и не проверяются через defined.

Рядом со скачанным example.php лежит fixtures/stock.txt с числом 12. File_get_contents получает полный путь и возвращает содержимое строкой либо false при отказе. Trim удаляет завершающий перевод строки; basename оставляет только имя файла из полного пути. Эти функции обслуживают путь и вывод, а сведения о месте кода дают сами специальные имена.

Прочитать запас и показать настоящую отметку исходникаСамостоятельный пример
<?php
function readStock(): string {
    $path = __DIR__ . '/fixtures/stock.txt';
    $body = file_get_contents($path);
    if ($body === false) { throw new RuntimeException('Учебный файл недоступен'); }
    return __FUNCTION__ . ': ' . trim($body);
}
echo readStock(), "\n";
echo 'Исходный файл: ', basename(__FILE__), "\n";
echo 'Метка строки: ', __LINE__, "\n";
Ожидаемый результат
readStock: 12
Исходный файл: example.php
Метка строки: 10

Вызов readStock() получает текст 12 из приложенного файла. __FUNCTION__ добавляет имя readStock, return передаёт готовую строку внешнему echo. __DIR__ привязывает путь к папке программы независимо от каталога запуска терминала. __FILE__ содержит полный путь; basename делает подпись переносимой. __LINE__ показывает настоящий номер строки в этом файле, а не проверку «номер больше нуля». При добавлении строк номер закономерно изменится; при переименовании example.php изменится имя. Файл запаса читается, но не изменяется.

__CLASS__, __METHOD__, __TRAIT__ и __NAMESPACE__ дают соответствующий контекст класса, метода, трейта и пространства имён. Не путайте __CLASS__ с классом объекта, который вызвал унаследованный метод: первый относится к месту объявления. __PROPERTY__ появился в PHP 8.4; ниже приведён отдельный пример с указанной версией.

Проверить наличие и обнаружить опечатку

В PHP 8 неизвестное имя не превращается в текст. Для необязательного правила defined проверяет существование по строковому имени. Возвращает bool: да/нет. if выбирает ветку, ! переворачивает ответ. Обязательную настройку проверяйте на старте и сообщайте об ошибке.

Явное значение по умолчаниюСамостоятельный пример
<?php
if (!defined('EXPORT_BATCH_SIZE')) {
    define('EXPORT_BATCH_SIZE', 20);
}
echo EXPORT_BATCH_SIZE;
Ожидаемый результат
20

Guard подходит для документированной возможности переопределения. При случайном конфликте двух файлов он скрывает проблему: останется значение первого. Для строгой конфигурации конфликт нужно обнаруживать.

Следующий пример использует try/catch и Error: try содержит чтение, catch перехватывает объект ошибки. Это наблюдение диагностики, а не привычный поиск настроек через исключения.

Опечатка вызывает ErrorСамостоятельный пример
<?php
try {
    echo UNKNOWN_DELIVERY_RULE;
} catch (Error $error) {
    echo "Нет объявления константы\n";
}
Ожидаемый результат
Нет объявления константы

На старых PHP встречалось предупреждение и использование неизвестного имени как строки. В PHP 8 проверьте имя, порядок подключений и namespace.

Константа-массив и отдельный рабочий список

Форма экспорта предлагает поддержанные форматы. Массив объединяет значения; [0] читает первый элемент, [] = добавляет в конец изменяемого массива. Набор в константе менять нельзя, но можно получить рабочую копию.

Показать исходные форматы и расширение для отчётаСамостоятельный пример
<?php
const EXPORT_FORMATS = ['csv', 'json'];
$formatsForReport = EXPORT_FORMATS;
$formatsForReport[] = 'txt';
echo "Общее правило:\n";
foreach (EXPORT_FORMATS as $format) { echo '- ', $format, "\n"; }
echo "Этот отчёт:\n";
foreach ($formatsForReport as $format) { echo '- ', $format, "\n"; }
Ожидаемый результат
Общее правило:
- csv
- json
Этот отчёт:
- csv
- json
- txt

Присваивание копирует значение массива в formatsForReport. Запись [] добавляет txt в изменяемую копию. Два foreach показывают сами элементы: исходное правило по-прежнему csv/json, рабочий список csv/json/txt. Это ещё перечень разрешённых названий, а не реализация кодирования этих форматов. Запись EXPORT_FORMATS[] = ... запрещена. Если массив содержит объекты, их внутреннее состояние требует отдельного разбора: копирование массива не клонирует объекты.

Чтение в функции без global

Функция читает уже объявленное глобальное правило напрямую. Константа не становится её локальной переменной и не требует global. define внутри функции тоже не создаёт локальную переменную: объявленное имя остаётся доступным после вызова. Различие подробно разобрано в области видимости.

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

Вернуть вместимость и использовать её после вызоваСамостоятельный пример
<?php
const ITEMS_PER_BOX = 6;
function twoBoxes(): int {
    return ITEMS_PER_BOX * 2;
}
$available = twoBoxes();
$reserved = 5;
$remaining = $available - $reserved;
echo 'В двух коробках: ', $available, "\n";
echo 'Зарезервировано: ', $reserved, "\n";
echo 'Осталось: ', $remaining, "\n";
Ожидаемый результат
В двух коробках: 12
Зарезервировано: 5
Осталось: 7

Вызов справа от = входит в twoBoxes. Тело читает ITEMS_PER_BOX=6, умножает на 2 и возвращает 12 точно в выражение twoBoxes(). Присваивание сохраняет 12 в available; следующая арифметика использует его для 12−5=7. Return сам ничего не печатает. Global для чтения константы не нужен. Если на двух складах разная вместимость, передайте её параметром вместо одного общего имени.

define не ограничивает имя телом функцииСамостоятельный пример
<?php
function registerExportLimit(): void
{
    define('FUNCTION_EXPORT_LIMIT', 25);
}
registerExportLimit();
echo FUNCTION_EXPORT_LIMIT;
Ожидаемый результат
25

До вызова имени ещё нет. Повторный вызов попытался бы объявить его снова: предупреждение, старое значение останется. void означает отсутствие полезного возвращаемого значения. Такой шаблон не подходит для разных параметров каждого заказа.

Полное имя и namespace

Каталог и доставка могут иметь разные LIMIT благодаря пространствам имён. namespace задаёт префикс обычных объявлений файла. const получает его автоматически; define получает готовую строку. Текущий namespace и use-псевдонимы к этой строке сами не добавляются.

Обычное объявление и строки для defineСамостоятельный пример
<?php
namespace Lesson\Catalog;
const PAGE_LIMIT = 12;
define('OUTSIDE_LIMIT', 4);
define(__NAMESPACE__ . '\\DYNAMIC_LIMIT', 8);
echo PAGE_LIMIT, "\n";
echo \OUTSIDE_LIMIT, "\n";
echo constant('Lesson\\Catalog\\DYNAMIC_LIMIT'), "\n";
Ожидаемый результат
12
4
8

__NAMESPACE__ даёт префикс, точка соединяет строки. OUTSIDE_LIMIT объявлен глобально. Для define передавайте полное имя без ведущего обратного слеша. constant читает значение по готовому строковому имени.

Обычное неполное имя константы внутри namespace сначала ищется в нём, затем может использовать глобальное имя. К классам это правило не относится. Для однозначности применяйте полный путь или use const.

Файл правил должен действительно выполнитьсяСамостоятельный пример
<?php
require __DIR__ . '/rules.php';
echo \Lesson\Shipping\MAX_PARCELS;
Ожидаемый результат
3

require выполняет приложенный rules.php, namespace только организует имена. Обычная автозагрузка классов сама не загружает свободные константы и функции. В Composer их файлы можно явно перечислить в autoload.files; классам подходит PSR-4.

Два модуля строят свои пути без конфликта имён

Реальная проблема из вопроса о define внутри namespace: два раздела хотят одинаковое короткое имя, но разные значения. Сначала ниже обычный const автоматически получает пространство. Во втором модуле define получает полное имя строкой. Это самостоятельный файл; фигурные скобки отделяют пространства, а завершающий namespace без имени — глобальный участок.

Получить два адреса из двух независимых правилСамостоятельный пример
<?php
namespace Shop\Catalog {
    const BASE_PATH = '/catalog/';
    const OFFERS_PATH = BASE_PATH . 'offers/';
}
namespace Shop\Delivery {
    define(__NAMESPACE__ . '\\BASE_PATH', '/delivery/');
    define(__NAMESPACE__ . '\\OFFERS_PATH', BASE_PATH . 'offers/');
}
namespace {
    echo 'Каталог: ', \Shop\Catalog\OFFERS_PATH, "\n";
    echo 'Доставка: ', constant('Shop\\Delivery\\OFFERS_PATH'), "\n";
}
Ожидаемый результат
Каталог: /catalog/offers/
Доставка: /delivery/offers/

В Catalog константное выражение складывает две строки точкой; результат /catalog/offers/. В Delivery __NAMESPACE__ даёт Shop\Delivery, добавление \BASE_PATH формирует имя для define. Следующий вызов читает собственный BASE_PATH и строит /delivery/offers/. В глобальном коде прямое полное имя и constant по строке получают готовые значения. Эти пути ещё не создают страницы сайта. Пространство не добавляется к строкам define автоматически; без префикса возникли бы общие глобальные имена.

Сравнение const/define из отдельного обсуждения следует проверять по текущему Manual: старые ответы описывают ограничения версий PHP 5. Простые строковые и арифметические константные выражения не требуют замены const на define. Если значение получено из переменной после загрузки конфигурации, используйте define или передайте его обычным параметром.

Имена, уже определённые PHP

PHP_VERSION_ID описывает версию числом, PHP_OS_FAMILY — семейство ОС, PHP_INT_SIZE — размер целого в байтах. Другие константы предоставляют расширения. Не запоминайте случайное числовое значение флага: используйте его документированное имя.

Предопределённое имя полезно, когда от него зависит следующий шаг. Ниже проверяется допустимость прибавления к целому: вместо потенциально переполняющего сложения сначала сравниваем прибавляемое число с оставшимся запасом до PHP_INT_MAX. Оба входа — уже проверенные неотрицательные int.

Проверить запас целого перед добавлением объёма партииСамостоятельный пример
<?php
$preparedBytes = 2000000000;
$nextBatchBytes = 100000000;
if ($nextBatchBytes > PHP_INT_MAX - $preparedBytes) {
    echo "Размер не помещается в целое этой сборки PHP\n";
} else {
    $totalBytes = $preparedBytes + $nextBatchBytes;
    echo 'После партии: ', $totalBytes, ' байт', "\n";
}
if (PHP_VERSION_ID >= 80200) {
    echo "Можно запустить утилиту для PHP 8.2+\n";
}
Ожидаемый результат
После партии: 2100000000 байт
Можно запустить утилиту для PHP 8.2+

PHP_INT_MAX даёт верхнюю границу int именно этой сборки. Ветвь else получает суммарные 2100000000 байт и печатает их; выбранное число помещается и в 32-, и в 64-битный int. Если прибавление не помещается, сложение не выполняется. 80200 обозначает 8.2.0: проверка версии разрешает сообщение о минимальном требовании, но не проверяет срок поддержки или расширения. Эти имена уже предоставляет PHP, объявлять их самостоятельно не нужно. Для отрицательных входов или уже полученного float эта проверка не является готовым универсальным алгоритмом.

Проверка версии внутри файла не спасает от неподдерживаемого синтаксиса в том же файле: сначала PHP должен его разобрать. Новый файл подключайте после проверки в совместимом загрузчике. Полный перечень специфических имён находится в соответствующих категориях расширений.

Специальные имена показывают место исходного кода

ЗаписьЧто обозначает
__LINE__Номер строки в месте записи.
__FILE__Полное имя текущего файла с разрешёнными символическими ссылками.
__DIR__Каталог этого файла.
__FUNCTION__Имя функции с namespace; в методе — имя метода.
__CLASS__Класс объявления; в трейте — использующий его класс.
__TRAIT__Имя трейта с namespace.
__METHOD__Имя метода с классом/трейтом.
__NAMESPACE__Текущее пространство имён, в глобальном — пустая строка.
__PROPERTY__ (8.4+)Имя свойства в его hook.
ИмяКласса::classОтдельная конструкция: разрешённое строковое имя класса.

Магические имена нечувствительны к регистру. Это не записи обычной таблицы констант: их не читают через constant и не проверяют defined. Контекст зависит от места записи. Для анонимных функций с PHP 8.4 сгенерированное имя содержит привязку к файлу и строке: это не устойчивый идентификатор между правками программы. Для абсолютных путей заранее определите, кому доступна диагностика; посетителю сайта путь к исходнику обычно не нужен.

Класс объявления и класс вызоваСамостоятельный пример
<?php
class BaseReport
{
    public static function identify(): void
    {
        echo __CLASS__, "\n";
        echo __METHOD__, "\n";
        echo static::class, "\n";
    }
}
class StockReport extends BaseReport {}
StockReport::identify();
Ожидаемый результат
BaseReport
BaseReport::identify
StockReport

Это пример после главы наследования: extends создаёт потомка, :: вызывает статический метод. __CLASS__/__METHOD__ описали исходное объявление, static::class — вызвавший класс. Так в журнале различают «где написан код» и «от чьего имени он работает».

Трейт и использующий его классСамостоятельный пример
<?php
namespace Lesson;
trait DescribeContext
{
    public function describe(): void
    {
        echo __TRAIT__, "\n";
        echo __CLASS__, "\n";
        echo __METHOD__, "\n";
        echo __FUNCTION__, "\n";
        echo __NAMESPACE__, "\n";
    }
}
class DeliveryClient { use DescribeContext; }
(new DeliveryClient())->describe();
Ожидаемый результат
Lesson\DescribeContext
Lesson\DeliveryClient
Lesson\DescribeContext::describe
describe
Lesson

use внутри класса подключает трейт, а не импортирует namespace. Подписи различают источник метода и получивший его класс. Они не доказывают, что доставка или запрос прошли успешно: для этого нужен результат операции.

__PROPERTY__ внутри записи свойства — PHP 8.4+Самостоятельный пример
<?php
class Parcel
{
    public int $weight {
        set {
            echo __PROPERTY__, "\n";
            $this->weight = $value;
        }
    }
}
$parcel = new Parcel();
$parcel->weight = 1200;
echo $parcel->weight;
Ожидаемый результат
weight
1200

Нужна глава свойств и property hooks: set перехватывает запись, value содержит новое значение. __PROPERTY__ обозначает weight. Здесь демонстрируется контекст, а не законченная модель посылки: единицы и допустимые значения проверяются отдельно. Синтаксис требует PHP 8.4+.

Вне подходящего контекста __CLASS__, __TRAIT__, __FUNCTION__, __METHOD__, __NAMESPACE__ и __PROPERTY__ дают пустую строку. __DIR__ не имеет завершающего разделителя, кроме корня; добавляем / сами. Вне метода __METHOD__ совпадает с __FUNCTION__. Имена анонимных классов, как и замыканий, генерирует движок; не делайте их устойчивыми ключами хранилища.

Константа с объектом не даёт глубокой неизменяемости

С PHP 8.1 объект может быть значением глобальной константы; const с new допустим в соответствующем глобальном контексте. Это не разрешение new в любом значении свойства или константе класса. Сначала изучите объекты: new создаёт объект, стрелка обращается к свойству.

Имя остаётся, состояние объекта меняетсяСамостоятельный пример
<?php
class DeliveryRule
{
    public int $limit = 3;
}
const DELIVERY_RULE = new DeliveryRule();
$rule = DELIVERY_RULE;
$rule->limit = 4;
echo DELIVERY_RULE->limit;
Ожидаемый результат
4

rule указывает на тот же объект. Константу не переназначали, но свойство изменили. Для фиксированного числа проще скаляр; для объекта нужны продуманные правила изменения и доступа. clone создаёт другой объект с отдельными ограничениями глубины копии.

Общий клиент с токеном в константе усложняет разные настройки двух интеграций и тесты. Явная передача настроенного объекта показывает зависимость — композиция и внедрение зависимостей.

PHP 8.5: приведения, Closure и first-class callable

Следующие файлы требуют PHP 8.5+. Приведения теперь допустимы в константных выражениях. Для Closure разрешена форма static function без захвата внешних переменных через use; fn здесь не заменяет её. Создание вызываемого значения не запускает тело функции.

Привести начальное значение — PHP 8.5+Самостоятельный пример
<?php
const RETRY_STEPS = (int) 3.8;
echo RETRY_STEPS;
Ожидаемый результат
3

Дробная часть отброшена. Обычно проще сразу записать целое 3; пример показывает допустимый синтаксис для чтения библиотек, а не проверку пользовательского ввода.

Объявить преобразование и вызвать позже — PHP 8.5+Самостоятельный пример
<?php
const LABEL_FORMATTER = static function (string $label): string {
    return '[' . $label . ']';
};
$format = LABEL_FORMATTER;
echo $format('SKU-17');
Ожидаемый результат
[SKU-17]

Константа хранит Closure. Присваивание даёт это значение format. Скобки после $format запускают функцию: аргумент становится label, return возвращает [SKU-17] в место вызова, echo выводит результат.

Взять существующую функцию — PHP 8.5+Самостоятельный пример
<?php
const LABEL_LENGTH = strlen(...);
$measure = LABEL_LENGTH;
echo $measure('SKU-17');
Ожидаемый результат
6

Три точки создают first-class callable; strlen ещё не вызывается. Запуск происходит через $measure. strlen считает байты, поэтому для кириллицы метрику выбирают отдельно.

PHP 8.5 также разрешает атрибуты у глобальных const. Это метаданные объявления; define не становится объявлением с атрибутом. Применение и получение через Reflection разобраны в главе атрибутов.

Выбрать инструмент по задаче

ЗадачаПереход
Объявить вычисленное правилоdefine
Проверить существованиеdefined
Прочитать значение по строке имениconstant
Исследовать таблицу для диагностикиget_defined_constants
Индивидуальные настройки двух клиентовПередать два настроенных объекта
Имена разных библиотек конфликтуютПространства имён

Попробуйте. У двух служб доставки лимиты 3 и 7 мест. Достаточно общей MAX_PARCELS?

Разбор

Нет: одно глобальное число не выражает два одновременно действующих ограничения. Передавайте лимит в функцию или храните в двух объектах настроек. Неизменность правила внутри расчёта не требует одной глобальной константы.

Для одного имени используйте defined: получение всей таблицы ради проверки создаёт лишний массив. Измеряйте время целой операции — обращение к API и обход большого набора обычно важнее микроразницы const/define.

Проверьте выбор: правило или изменяемые данные

  • Не вызывайте define второй раз для изменения настройки; создайте отдельную переменную или объект настроек.
  • Не записывайте секреты в публичный репозиторий только потому, что назвали их константами.
  • Не прячьте неограниченное число настроек за defined: обязательную ошибку конфигурации лучше обнаружить явно.

Попробуйте сами. Показываем по 4 товара. Для 9 товаров ожидается 3 страницы, для пустого списка — 0. Что поменять в первом примере и где хранить текущий номер страницы?

Разбор и проверка

Замените значение PAGE_SIZE на 4, количество каталога — на 9. Текущая страница меняется от запроса к запросу, поэтому это проверенная переменная, а не ещё одна константа. Для нуля формула даёт 0; отрицательные значения отклоняет функция из второго примера.

Функции и методы этой темы

Откройте карточку, чтобы увидеть договор функции, примеры, ограничения и связанные инструменты.

defineОбъявить константу во время выполнения по строковому имени и уже проверенному значению.

PHP 4+; object value — PHP 8.1+ · standard

define(string $constant_name, mixed $value, bool $case_insensitive = false): bool

Объявить константу во время выполнения по строковому имени и уже проверенному значению.

Скобки после имени запускают вызов; значения внутри — аргументы. Знак = сохраняет возвращённый результат в переменную со знаком $. Функция может вернуть число, строку, массив, true/false либо завершить текущий сценарий. Сначала смотрите минимальный вызов и ожидаемый результат, затем переходите к условиям, функциям и обработке ошибок. Как устроен вызов, параметр и return.

Что произойдёт при вызове

Проверенная настройка → общее имя
  1. Получить настройку
  2. Проверить тип и диапазон
  3. define регистрирует значение один раз
  4. Код читает константу по имени

Первый запуск и развитие задачи

Если значение меняется или два клиента одновременно имеют разные настройки, используйте переменные/объекты конфигурации. Для буквального значения в исходнике обычно яснее const.

Полный договор вызова

Часть вызоваПолный договор
constant_nameОбычная строка. Для namespaced-константы передайте полное имя без начального обратного слеша. Зарезервированные/невалидные имена технически возможны, но читать их можно только через constant и создавать их не рекомендуется.
valueЗначение; объект разрешён с PHP 8.1. Ресурс технически допустим, но Manual предупреждает о непредсказуемом поведении.
case_insensitiveОставляйте false. true deprecated с 7.3 и с 8.0 даёт E_WARNING; регистронезависимые пользовательские константы больше не поддерживаются.
Возвратtrue при объявлении, false при отказе. Это статус, а не объявленное значение.

Ошибки и границы. Повторное имя вызывает диагностику и не заменяет прежнее значение. Внешний ввод сначала валидируется: define не знает предметных ограничений.

Версии и платформа. PHP 8 принимает только false для case_insensitive; ведущий обратный слеш в строковом имени не нормализуется.

Рядом: defined, constant.

Карта полного раздела Miscellaneous.

Нужна, когда именованное правило вычисляется во время выполнения. Например, настройки прочитаны и проверены до регистрации общего размера пакета импорта. Если значение буквально записано в исходнике, const обычно проще.

Параметр / результатСмысл
constant_name: stringИмя константы; строка не получает текущий namespace или use-псевдонимы автоматически.
value: mixedОбъявляемое значение. Массивы поддерживаются с PHP 7, объекты — с 8.1. Ресурсы не используйте как постоянную конфигурацию.
case_insensitive: bool = falseОставьте false. В PHP 8 регистронезависимые пользовательские константы не поддерживаются; true вызывает предупреждение.
Возврат: boolУспех объявления, а не объявленное значение. При повторном имени — предупреждение и false; прежнее значение остаётся.

Сначала отделим статус от значения. Define получает два аргумента: строку имени и число 10. Его bool-возврат попадёт в created и управляет сообщением; объявленное число читается по имени MANUAL_PAGE_SIZE и участвует в расчёте свободных мест.

Использовать статус объявления и само правило отдельноСамостоятельный пример
<?php
$created = define('MANUAL_PAGE_SIZE', 10);
if ($created) { echo "Размер страницы установлен\n"; }
$shown = 7;
$free = MANUAL_PAGE_SIZE - $shown;
echo 'Показано: ', $shown, ' из ', MANUAL_PAGE_SIZE, "\n";
echo 'Свободных мест: ', $free, "\n";
Ожидаемый результат
Размер страницы установлен
Показано: 7 из 10
Свободных мест: 3

Define возвращает true, поэтому if печатает первую строку. MANUAL_PAGE_SIZE содержит 10, а не true. Вычитание 10−7 даёт 3 в free; оба числа используются в отчёте. Если написать $pageSize=define(...), в pageSize окажется bool: он не заменит числовое правило. Повторное объявление имени вызывает предупреждение и возвращает false; прежнее значение сохраняется.

Дальше используем массив настроек, проверку типа is_int и if. Знак || означает «или», ! — отрицание. throw прекращает неподходящую инициализацию через исключение: это уже стадия после глав условий и исключений.

Разбить проверенный список на пакеты выбранного размераСамостоятельный пример
<?php
$settings = ['batchSize' => 2];
$batchSize = $settings['batchSize'];
if (!is_int($batchSize) || $batchSize < 1 || $batchSize > 100) {
    throw new InvalidArgumentException('Размер должен быть от 1 до 100');
}
define('MANUAL_BATCH_SIZE', $batchSize);
$jobs = ['SKU-10', 'SKU-20', 'SKU-30', 'SKU-40', 'SKU-50'];
$batches = array_chunk($jobs, MANUAL_BATCH_SIZE);
foreach ($batches as $index => $batch) {
    echo 'Пакет ', $index + 1, ': ', implode(', ', $batch), "\n";
}
Ожидаемый результат
Пакет 1: SKU-10, SKU-20
Пакет 2: SKU-30, SKU-40
Пакет 3: SKU-50

Settings имитирует уже прочитанную конфигурацию. Is_int принимает целое 2, диапазон 1..100 допускает его. Define регистрирует 2; array_chunk возвращает три массива по два, два и одному артикулу. Implode получает разделитель и очередной массив, возвращает текст артикулов в echo. Это план пакетов, отправки во внешнюю систему нет. При batchSize=3 будут пакеты SKU-10/20/30 и SKU-40/50; при 0, 101 или строке "2" проверка прервёт инициализацию до define. Диапазон — правило этого импортёра, не ограничение define.

Не переопределяйте имя для каждого нового заказа. Различающиеся настройки храните в аргументах или объектах. Нельзя создать константу класса вызовом define. Для namespaced-константы задавайте полное строковое имя без начального обратного слеша. Объектное значение не становится глубоко неизменяемым. Встроенная функция не шифрует секрет, если передать токен как value.

Сначала: объявление и чтение константы. Рядом: defined, constant, get_defined_constants.

Полный контракт допускает необычные или зарезервированные строковые имена, которые можно читать только через constant; для нового кода выбирайте обычные идентификаторы. В отличие от constant/defined функция define не удаляет ведущий обратный слеш: имя вида \App\LIMIT может успешно зарегистрироваться, но обычное чтение его не найдёт. Передавайте App\LIMIT. Ресурс технически может быть значением, но официальный Manual предупреждает о непредсказуемых результатах; используйте явную переменную времени жизни ресурса.

definedПроверить, существует ли константа, не пытаясь читать отсутствующее имя.

PHP 4+ · standard

defined(string $constant_name): bool

Проверить, существует ли константа, не пытаясь читать отсутствующее имя.

Скобки после имени запускают вызов; значения внутри — аргументы. Знак = сохраняет возвращённый результат в переменную со знаком $. Функция может вернуть число, строку, массив, true/false либо завершить текущий сценарий. Сначала смотрите минимальный вызов и ожидаемый результат, затем переходите к условиям, функциям и обработке ошибок. Как устроен вызов, параметр и return.

Что произойдёт при вызове

Необязательное правило
  1. Есть строка имени
  2. defined отвечает только о наличии
  3. При true — constant читает значение
  4. При false — явная запасная политика

Первый запуск и развитие задачи

Обязательную конфигурацию не стоит молча подменять запасным значением: сообщите об ошибке запуска. Для одной константы не выгружайте всю таблицу get_defined_constants.

Полный договор вызова

Часть вызоваПолный договор
constant_nameСтроковое полное имя глобальной/namespaced/class-константы или enum-case. Namespace и use к строке автоматически не добавляются.
Возвратtrue, если доступное имя объявлено, иначе false. Значение false или null всё равно считается объявленным.
Не проверяетПеременные проверяет isset/array_key_exists, функции — function_exists.

Ошибки и границы. false сообщает отсутствие; это не исключение и не оценка истинности самого значения.

Версии и платформа. Работает с константами классов и enum-case при соблюдении загрузки и видимости.

Рядом: constant, define.

Карта полного раздела Miscellaneous.

Проверяет существование константы до чтения. Это удобно для необязательной настройки старого модуля. Наличие объявления и смысл значения — разные вопросы: false или null могут быть корректно объявленными значениями.

Часть контрактаЧто означает
constant_name: stringСтроковое имя глобальной, namespaced или доступной константы класса; поддерживаются и имена enum-case.
booltrue — имя найдено, false — нет доступного объявления. Это не проверка переменной или функции.
Строковые именаНе переписываются use-псевдонимами; используйте полное имя. Для динамического имени класса важны загрузка и правила доступа.
Не спутать отключённую подпись с отсутствующей настройкойСамостоятельный пример
<?php
const MANUAL_SIGNATURE = null;
if (defined('MANUAL_SIGNATURE')) {
    $signature = MANUAL_SIGNATURE;
    echo 'Настройка найдена: ', $signature ?? 'подпись отключена', "\n";
} else {
    echo "Настройки нет: используется подпись магазина\n";
}
if (!defined('MANUAL_FOOTER')) {
    echo "Нижний текст не настроен\n";
}
Ожидаемый результат
Настройка найдена: подпись отключена
Нижний текст не настроен

Defined возвращает true для существующего MANUAL_SIGNATURE даже при значении null. Поэтому читается настройка и ?? выбирает пояснение отключения. Для MANUAL_FOOTER объявления нет: defined возвращает false, ! разрешает второе сообщение. Здесь null — наше соглашение «подпись отключена». Если удалить первое объявление, выполнится другая ветка с подписью магазина. Это отличается от isset для переменных, где null даёт false.

В следующем примере оператор ? : выбирает один из двух результатов: после ? — при наличии имени, после : — при отсутствии. constant читает уже проверенное имя. В применении ниже str_pad возвращает строку заданной ширины; её параметры и байтовое ограничение объяснены после кода.

Использовать явный запасной размер этикеткиСамостоятельный пример
<?php
const MANUAL_LABEL_WIDTH = 12;
$width = defined('MANUAL_LABEL_WIDTH') ? constant('MANUAL_LABEL_WIDTH') : 8;
$sku = 'SKU-7';
$label = str_pad($sku, $width, '.', STR_PAD_RIGHT);
echo '|', $label, '|', "\n";
Ожидаемый результат
|SKU-7.......|

Defined находит имя: условие выбирает constant(...), который возвращает int 12 в width. Str_pad получает текст из пяти ASCII-байтов, ширину 12, заполнитель "." и направление справа; возвращает SKU-7 с семью точками в label. Echo ставит видимые границы. Без объявления width стал бы 8 и добавились бы три точки. Это ширина в байтах, не экранных колонках для произвольного Unicode. Обязательную настройку нельзя молча заменять этим запасным правилом.

Передавайте имя строкой: попытка сначала вычислить неизвестную константу вызовет Error до самой проверки. Наличие имени не означает доступность сервера, корректность токена или включённость функции приложения. Для одного имени defined проще и дешевле по объёму создаваемых данных, чем выгрузка всей таблицы констант.

Сначала: объявление и чтение константы. Рядом: define, constant, get_defined_constants.

constantПолучить значение уже объявленной константы, когда её имя хранится в строке.

PHP 4.0.4+; Error для отсутствующего имени — PHP 8.0+ · standard

constant(string $name): mixed

Получить значение уже объявленной константы, когда её имя хранится в строке.

Скобки после имени запускают вызов; значения внутри — аргументы. Знак = сохраняет возвращённый результат в переменную со знаком $. Функция может вернуть число, строку, массив, true/false либо завершить текущий сценарий. Сначала смотрите минимальный вызов и ожидаемый результат, затем переходите к условиям, функциям и обработке ошибок. Как устроен вызов, параметр и return.

Что произойдёт при вызове

Строковое имя → значение
  1. Получить или составить разрешённое имя
  2. Проверить optional-имя через defined
  3. constant находит объявление
  4. Использовать значение с его исходным типом

Первый запуск и развитие задачи

Прямое LIMIT проще, когда имя известно в исходнике. Динамическое имя полезно для совместимости с таблицей профилей; не позволяйте посетителю читать произвольные внутренние константы.

Полный договор вызова

Часть вызоваПолный договор
nameПолное строковое имя. Текущий namespace, namespace\ и use-псевдонимы к строке не применяются. Namespace-часть регистронезависима, конечное имя константы — нет.
ВозвратИсходное значение любого допустимого типа; также работают доступные константы классов и enum-case.
Отсутствующее имяС PHP 8 выбрасывается Error; до 8.0 было E_WARNING и null. Для необязательного имени сначала defined.

Ошибки и границы. Неизвестное имя — Error. Наличие имени не подтверждает корректность или безопасность его значения.

Версии и платформа. Строковое имя не получает namespace автоматически; это существенная граница, а не только синтаксическая деталь.

Рядом: defined, define.

Карта полного раздела Miscellaneous.

Получает значение, когда имя известно только как текст. Например, старый модуль связывает выбранный профиль с названием одной из известных констант. Если имя буквально известно в коде, прямое обращение проще.

Часть контрактаЧто означает
name: stringПолное строковое имя. Конечное имя пользовательской константы чувствительно к регистру; часть namespace в таком строковом имени регистронезависима. Сохраняйте единое написание для читаемости.
mixedЗначение найденной константы с его исходным типом. Это не обязательно строка.
Неизвестное имяВ PHP 8 выбрасывается Error. Для необязательных имён сначала defined; старое поведение с предупреждением и null не является текущим контрактом.
ClassName::CONSTANT / EnumName::CaseДопустимые формы при соблюдении загрузки и доступа. use не меняет строку автоматически.
Прочитать лимит по строке и рассчитать остатокСамостоятельный пример
<?php
const MANUAL_MAX_ROWS = 30;
$name = 'MANUAL_MAX_ROWS';
$limit = constant($name);
$prepared = 12;
echo 'Правило: ', $name, "\n";
echo 'Готово строк: ', $prepared, ' из ', $limit, "\n";
echo 'Можно добавить: ', $limit - $prepared, "\n";
Ожидаемый результат
Правило: MANUAL_MAX_ROWS
Готово строк: 12 из 30
Можно добавить: 18

Name хранит буквы MANUAL_MAX_ROWS. Constant получает эту строку, находит объявление и возвращает целое 30 в limit. Обычный echo name печатает название; вычитание использует возвращённое число 30−12=18. Это не вызов функции по имени и не чтение переменной со знаком $. Если название постоянно известно автору, присваивание limit = MANUAL_MAX_ROWS проще.

Для выбора из внешнего запроса создайте разрешённое отображение: ключ массива — короткое название профиля, значение — допустимое имя. isset проверяет, что такой элемент есть и не равен null; после этого разрешаем чтение.

Выбрать разрешённое правило и получить две группы артикуловСамостоятельный пример
<?php
const MANUAL_SMALL_BATCH = 2;
const MANUAL_LARGE_BATCH = 4;
$profiles = ['small' => 'MANUAL_SMALL_BATCH', 'large' => 'MANUAL_LARGE_BATCH'];
$requested = 'small';
if (!isset($profiles[$requested])) {
    throw new InvalidArgumentException('Неизвестный профиль');
}
$constantName = $profiles[$requested];
$size = constant($constantName);
$parts = array_chunk(['TEA', 'COFFEE', 'CUP'], $size);
foreach ($parts as $index => $items) {
    echo 'Группа ', $index + 1, ': ', implode(', ', $items), "\n";
}
Ожидаемый результат
Группа 1: TEA, COFFEE
Группа 2: CUP

Вход small выбирает строку MANUAL_SMALL_BATCH из разрешённого отображения. Constant возвращает её значение 2 в size. Array_chunk создаёт [TEA,COFFEE] и [CUP], foreach показывает обе группы. При large размер 4 поместит все три артикула в одну группу. Unknown будет отклонён до чтения константы. В новом модуле часто проще хранить сами числа в profiles; строковые имена полезны для совместимости с существующим договором конфигурации.

Магические имена __DIR__/__FILE__ так не читаются: пишите их непосредственно в месте кода. Не принимайте от посетителя произвольное имя без ограничения выбора — внутренние константы могут содержать конфиденциальные настройки.

Сначала: объявление и чтение константы. Рядом: define, defined, get_defined_constants.

get_defined_constantsПолучить константы текущего процесса одним списком или по группам расширений.

Есть в проверенном PHP 8.5.11 · Core

get_defined_constants(bool $categorize = false): array

Получить константы текущего процесса одним списком или по группам расширений.

Без аргумента результат — name=>value. categorize=true группирует системные константы по расширению, а объявленные приложением помещает в user. Magic constants вроде __FILE__ в список не входят: они разрешаются компилятором в зависимости от места кода. Это инструмент исследования и закрытой диагностики; постоянный код обычно обращается к известной константе через defined/constant.

Первый запуск и развитие задачи

Найти собственные константы отдельно от системныхСамостоятельный пример
<?php
declare(strict_types=1);

define('SHOP_DEFAULT_CURRENCY', 'RUB');
$groups = get_defined_constants(true);
echo $groups['user']['SHOP_DEFAULT_CURRENCY'], "\n";
echo isset($groups['Core']['PHP_VERSION']) ? "ядро отдельно\n" : "нет Core\n";
Ожидаемый результат
RUB
ядро отдельно

Аргумент true группирует значения по расширениям и выделяет user. Полный системный список велик; в обычной диагностике выводите только нужные имена.

Собрать белый список возможностей и локально отбросить подробные отчётыСамостоятельный пример
<?php
declare(strict_types=1);

$coreReady = extension_loaded('Core');
$constants = get_defined_constants(false);
$ordinary = get_loaded_extensions(false);
$zend = get_loaded_extensions(true);

ob_start();
$creditsOk = phpcredits(CREDITS_QA);
ob_end_clean();
ob_start();
$infoOk = phpinfo(INFO_MODULES);
ob_end_clean();
$engine = zend_version();

$capabilitiesOk = $coreReady && isset($constants['PHP_VERSION'])
    && in_array('Core', $ordinary, true) && is_array($zend);
$reportsOk = $creditsOk === true && $infoOk === true && $engine !== '';
echo $capabilitiesOk ? "возможности подтверждены\n" : "неполная среда\n";
echo $reportsOk ? "локальные отчёты сформированы и отброшены\n" : "ошибка отчёта\n";
Ожидаемый результат
возможности подтверждены
локальные отчёты сформированы и отброшены

Пример отличается от полного inventory: код проверяет конкретные факты, phpcredits/phpinfo удерживает в локальном буфере и удаляет, а наружу отдаёт только две безопасные фразы.

Полный договор вызова

ПараметрЧто передаём и зачем
categorizefalse — плоский массив; true — группы расширений и user.
Часть договораЧто получает программа
Сигнатураget_defined_constants(bool $categorize = false): array
Результатarray.
Ошибки и особые значенияМассив велик и может меняться с составом расширений. Не сериализуйте его как стабильный внешний контракт и не печатайте целиком публично.
ВерсииЕсть в проверенном PHP 8.5.11
Официальный диапазон узла: (PHP 4 >= 4.1.0, PHP 5, PHP 7, PHP 8).
СредаВсе SAPI, если ниже не указано иное.

Более простой или безопасный выбор. Проверяйте одну возможность через defined("NAME") и объясняйте fallback.

Рядом: extension_loaded, get_loaded_extensions, phpinfo.

Вернуться к карте задач или полному дереву функций.

Сначала увидим форму плоского результата, затем готовый диагностический отчёт из двух выбранных имён. Возвращённая таблица — массив, а не текст для автоматической публикации. $constants['MANUAL_EXPORT_LIMIT'] читает значение по ключу; вариант true добавляет ещё один уровень группировки.

Полезна при создании локальной диагностической утилиты: показывает имена, объявленные в текущем процессе. Не является полным списком всего, что может существовать в другой сборке PHP.

Параметр / результатСмысл
categorize: bool = falsefalse — плоский массив имя → значение; true — группы по расширениям. Пользовательские объявления попадают в user.
arrayСнимок текущей таблицы; состав зависит от версии, расширений и уже выполненных объявлений.
Что не входитМагические константы и константы классов. Для класса применяют ReflectionClass.
Прочитать свою запись из таблицыСамостоятельный пример
<?php
const MANUAL_EXPORT_LIMIT = 40;
$constants = get_defined_constants();
echo $constants['MANUAL_EXPORT_LIMIT'];
Ожидаемый результат
40

Ключ массива — строка имени. Это знакомство с формой результата; получать всю таблицу ради единственного известного числа в обычной программе не требуется.

В сгруппированном варианте сначала берём user. Оператор ?? [] даёт пустой массив, если группа отсутствует. foreach далее проходит только явно разрешённый список имён, а не все внутренние настройки.

Показать только выбранные безопасные настройкиСамостоятельный пример
<?php
const MANUAL_PUBLIC_PAGE_SIZE = 20;
const MANUAL_PUBLIC_FORMAT = 'csv';
$groups = get_defined_constants(true);
$userConstants = $groups['user'] ?? [];
foreach (['MANUAL_PUBLIC_PAGE_SIZE', 'MANUAL_PUBLIC_FORMAT'] as $name) {
    echo $name, '=', $userConstants[$name], "\n";
}
Ожидаемый результат
MANUAL_PUBLIC_PAGE_SIZE=20
MANUAL_PUBLIC_FORMAT=csv

Обе константы объявлены в этом самостоятельном примере. В реальной диагностике учитывайте отсутствие ожидаемого имени и не выводите всю группу публично: в ней могут находиться ключи интеграций.

Функция строит массив; не вызывайте её заново для каждой строки большого импорта. Для наличия одного имени подходит defined. Не делайте вывод о работоспособности сервиса по наличию его константы. Количество записей не фиксировано и не подходит для переносимого теста.

Сначала: объявление и чтение константы. Рядом: define, defined, constant.

Источники и обсуждения

Код и руководство с собой

Скачайте самостоятельные примеры с исходными данными, инструкциями и ожидаемыми результатами. Примеры HTTP и фрагменты для проекта помечены отдельно: им нужно указанное окружение.

Код не исполняется на сайте. Скачайте нужный пример и запускайте его в своём локальном окружении.

Материалы сверены 2026-10-12. Примеры и объяснения написаны для этого руководства; источники и обсуждения доступны в каждой главе.