Перейти к содержимому
Поиск
Php Разработка

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

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

Александр НекрасовИзменено:
Практический мануал PHP: от переменных и функций к объектной модели интернет-магазина
PHP 8.5.11149 глав4458 карточек справочника
Дерево руководства

Глава 111 · От основ к практике

Tokenizer: понять PHP-исходник, не выполняя его

Полная категория Tokenizer: функции, PhpToken, позиции, TOKEN_PARSE, каталог T_*, анализ шаблонов и осторожное преобразование исходников.

Зачем разбирать код как данные

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

Исходный PHP-код становится данными анализатора

Анализируем запись программы, не выполняя её.

  1. <?php $price = 7;

    Строка исходника — входные данные.

  2. PhpToken::tokenize

    Разбивает текст на элементы с ID, текстом, строкой и байтовой позицией.

  3. $price / T_VARIABLE / pos 6

    Точный фрагмент с понятным видом и координатами.

  4. Подсветка или отчёт

    Правило анализатора выбирает нужные элементы.

Лексер не знает бизнес-смысл и не запускает анализируемый код. Для сложного преобразования требуется разбор структуры.

Вы сопровождаете сайт и хотите найти места, где разработчик подавил ошибку оператором @. Простой поиск текста захватит адреса электронной почты и комментарии. Tokenizer помогает отличить запись программы от текста внутри неё. На таком же механизме строятся подсветка, отчёты о стиле и часть инструментов преобразования исходников.

От одного файла к полезной подсказке
  1. Строка: <?php @readfile("missing.txt");
  2. Сканер видит отдельный знак @
  3. Анализатор запоминает строку и позицию
  4. Отчёт предлагает проверить обработку ошибки

Токен — кусочек исходного текста с назначением: имя переменной, число, слово echo или знак ;. Лексический анализатор разбивает текст, но не запускает этот код. В примерах строка '<?php echo 7;' — данные для анализатора. Само число 7 он не выводит. $tokens хранит полученный список; foreach по очереди рассматривает его элементы.

Вариант с объектами хранит каждый кусочек в PhpToken: ->text читает текст, ->is(...) задаёт вопрос о его виде. ::tokenize(...) вызывается у класса и создаёт список объектов. Основа синтаксиса: переменные, массивы, перебор, классы и объекты.

Первый результат: узнать, где переменнаяСамостоятельный пример
<?php
declare(strict_types=1);

$source = '<?php $price = 7;';
$tokens = PhpToken::tokenize($source);
echo $tokens[1]->text, "\n";
echo $tokens[1]->getTokenName(), "\n";
Ожидаемый результат
$price
T_VARIABLE

Переменная $source содержит текст другой программы. [1] берёт второй элемент списка: первый — открывающий тег. ->text читает исходную запись; getTokenName() возвращает её вид. Для произвольного файла фиксированный индекс не подходит — дальше используем перебор.

Аналогия — разложить предложение на слова и знаки с подписями. Она ограничена: PHP имеет состояния сканера, интерполяцию, теги и составные конструкции. Токены ещё не объясняют, какую задачу решает программа, и не составляют полноценное дерево выражений.

Установка, версии и границы инструмента

Tokenizer использует лексический сканер Zend Engine. Расширение включено по умолчанию; при собственной сборке его можно отключить параметром --disable-tokenizer. На Windows поддержка встроена: отдельную DLL tokenizer подключать не требуется. Отдельных конфигурационных директив для этой категории нет. Объект PhpToken доступен с PHP 8.0, две процедурные функции — с PHP 4.2.

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

var_dump(extension_loaded('tokenizer'));
var_dump(function_exists('token_get_all'));
var_dump(class_exists(PhpToken::class));
Ожидаемый результат
bool(true)
bool(true)
bool(true)

Это результат стенда PHP 8.5.11. Если tokenizer отключён в сборке, вызов отсутствующей функции не станет запасным режимом; приложение должно сообщить об отсутствии зависимости.

Анализатор следует версии того PHP, где запущен, а не версии, указанной в комментарии исходного файла. PHP 8.2 не научится оператору из PHP 8.5 от добавления константы в пользовательский код. Числовые значения T_* меняются; сравнивайте именованные константы. Для анализа нескольких версий нужен инструмент с явно выбранной грамматикой.

ПотребностьПодход
Подписи элементов, подсветка, ограниченный отчётTokenizer с исходными текстами и координатами.
Найти имена/выражения с учётом вложенности и namespaceПарсер AST; правила преобразования и сохранения форматирования.
Проверить синтаксис файла целевой версиейphp -l на нужной версии; это не полноценное выполнение.
Проверить бизнес-результат программыТесты в её окружении; Tokenizer не знает правильный остаток товара.

Токенизация не выполняет исходный код. Это не повод принимать неограниченный вход: исходная строка и массив/объекты занимают память, а разбор требует времени. Сначала задайте лимит размера. Не обещайте фиксированный выигрыш одного API над другим — измеряйте на своих файлах.

PhpToken: четыре поля и единый интерфейс

СвойствоСодержание
public int $idВид токена; для одиночного знака — его байтовое значение.
public string $textТочный фрагмент исходника; не результат вычисления.
public int $lineНачальная строка, начиная с 1; вручную по умолчанию -1.
public int $posБайтовое смещение с 0; вручную по умолчанию -1.
Те же данные в двух формах
  1. token_get_all: массив [ID, text, line] либо отдельный знак
  2. PhpToken::tokenize: каждый элемент — объект
  3. Объект добавляет pos и методы проверок
  4. Выбираем удобный интерфейс, не меняя смысл исходника

PhpToken реализует Stringable и допускает наследование. Его конструктор final, а tokenize возвращает объекты класса, у которого вызван. Поля доступны для изменения, но изменение text не пересчитывает id, pos и line. Эта структура описывает результат разбора, а не автоматически поддерживаемое дерево программы.

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

$source = '<?php /* я */ $price = 7;';
foreach (PhpToken::tokenize($source) as $token) {
    if ($token->is(T_VARIABLE)) {
        var_dump(substr($source, $token->pos, strlen($token->text)) === '$price');
        echo 'byte offset: ', $token->pos, "\n";
    }
}
Ожидаемый результат
bool(true)
byte offset: 15

Русская буква я занимает два байта UTF-8, поэтому байтовая позиция отличается от числа видимых символов перед ней. substr и strlen здесь работают с байтами, что соответствует pos. Это не правило для обрезки пользовательского текста на экране.

TOKEN_PARSE: лексический вид зависит от грамматического места

Единственный описанный флаг этой категории — TOKEN_PARSE. Он позволяет корректно распознавать зарезервированные слова там, где язык разрешает их использовать как имена. Флаг появился в PHP 7.0. Разница показана в token_get_all: PUBLIC внутри const может иметь вид T_STRING. При неверной грамматике получают ParseError; это надо отличать от запуска программы.

Правильная грамматика ещё не означает существование функцииСамостоятельный пример
<?php
declare(strict_types=1);

$tokens = PhpToken::tokenize('<?php missingShopFunction();', TOKEN_PARSE);
echo 'parsed tokens: ', count($tokens), "\n";
Ожидаемый результат
parsed tokens: 5

Анализатор принял форму вызова. Он не пытался вызвать missingShopFunction и не доказал, что она существует. Проверка синтаксиса, разрешение имён и выполнение — разные этапы.

Без TOKEN_PARSE сканер удобен для промежуточного текста в редакторе. Это не обещание принять любую последовательность байтов: некоторые ошибки лексического уровня всё равно возможны. Внешние исходники разбирайте с обработкой исключений и ограничением размера.

Полный каталог T_*: запись, назначение и версии

Таблица охватывает имена из официального приложения «List of Parser Tokens», включая исторические. Наличие строки в таблице не означает наличие константы в каждой версии PHP. Проверяют defined("T_PIPE"), если анализатор работает на нескольких версиях. Не задавайте вымышленные числовые ID отсутствующим токенам: сканер старого PHP всё равно не выучит новую грамматику.

Запись в средней колонке показывает характерный синтаксис, а не обещает точные границы text во всех контекстах. Для знаков ;, +, скобок и многих других односимвольных элементов T_*-константы нет. У token_get_all это строка, у PhpToken — объект с соответствующим однобайтовым ID.

ТокенХарактерная записьНазначение и важная граница
T_ABSTRACTabstractАбстрактный класс или метод: определяет обязательства для наследника.
T_AMPERSAND_FOLLOWED_BY_VAR_OR_VARARG&PHP 8.1+: амперсанд перед переменной или ...; нужен, например, для передачи по ссылке. Роль определяется грамматикой.
T_AMPERSAND_NOT_FOLLOWED_BY_VAR_OR_VARARG&PHP 8.1+: другой контекст амперсанда, например пересечение типов. Нельзя определять смысл только по тексту &.
T_AND_EQUAL&=Присвоение результата побитового И.
T_ARRAYarrayДлинная запись массива либо слово типа array. Круглые скобки — отдельные элементы.
T_ARRAY_CAST(array)Явное преобразование значения в массив.
T_ASasСвязывает элемент с переменной в foreach; встречается и при задании псевдонима.
T_ATTRIBUTE#[PHP 8.0+: начало атрибута. Это уже не обычный комментарий #.
T_BAD_CHARACTERуправляющий байтPHP 7.4+: недопустимые управляющие байты ASCII ниже 32, кроме табуляции, LF и CR. Это не любой неправильный символ UTF-8.
T_BOOLEAN_AND&&Логическое И с коротким замыканием.
T_BOOLEAN_OR||Логическое ИЛИ с коротким замыканием.
T_BOOL_CAST(bool), (boolean)Явное преобразование в логическое значение.
T_BREAKbreakВыход из цикла или switch; уровень вложенности разбирается отдельно.
T_CALLABLEcallableОбъявление вызываемого типа; не обозначает конкретную функцию.
T_CASEcaseВетка switch или case перечисления: нужен контекст.
T_CATCHcatchОбработчик выброшенного исключения.
T_CLASSclassОбъявление класса либо часть ::class; один токен не доказывает наличие объявления.
T_CLASS_C__CLASS__Магическая константа имени класса; значение появляется при обработке программы.
T_CLONEcloneСоздание копии объекта с правилами клонирования.
T_CLOSE_TAG?>Закрывающий PHP-тег; исторический %> больше не поддерживается в PHP 7+.
T_COALESCE??Выбор запасного значения при null или отсутствующем значении.
T_COALESCE_EQUAL??=PHP 7.4+: присваивание, если значение отсутствует или равно null.
T_COMMENT//, #, /* ... */Обычный комментарий вместе с его текстом. Строковый литерал с // не становится комментарием.
T_CONCAT_EQUAL.=Дописать строку к переменной.
T_CONSTconstОбъявить константу; область объявления определяется окружением.
T_CONSTANT_ENCAPSED_STRING'price', "price"Заключённая в кавычки строка без разбиваемой интерполяции. Содержимое ещё хранит исходную запись, а не вычисленное PHP-значение.
T_CONTINUEcontinueПерейти к следующему шагу цикла; правила switch внутри цикла требуют отдельного внимания.
T_CURLY_OPEN{$Начало сложной интерполяции внутри строки; фактический текст токена и соседние токены смотрите в результате сканера.
T_DEC--Уменьшение; положение до или после переменной влияет на значение выражения.
T_DECLAREdeclareДиректива выполнения или компиляции для участка/файла.
T_DEFAULTdefaultЗапасная ветвь switch/match. Само слово не задаёт выполняемое действие.
T_DIR__DIR__Магическая константа каталога файла.
T_DIV_EQUAL/=Деление с присваиванием результата.
T_DNUMBER0.12, 1e3Запись числа с плавающей точкой; исходная запись остаётся текстом.
T_DOdoНачало цикла с проверкой условия после тела.
T_DOC_COMMENT/** ... */Документационный комментарий. Парсер его пропускает, но IDE и библиотеки могут читать.
T_DOLLAR_OPEN_CURLY_BRACES${Историческая форма интерполяции ${...}; соответствующие формы устаревают с PHP 8.2. Не советуем её для нового кода.
T_DOUBLE_ARROW=>Связь ключа со значением, ветвь match или тело стрелочной функции — нужен контекст.
T_DOUBLE_CAST(double), (float)Приведение к float. Историческое (real) удалено в PHP 8.0.
T_DOUBLE_COLON::Псевдоним T_PAAMAYIM_NEKUDOTAYIM: обращение к члену класса или ::class.
T_ECHOechoВывод значения. Не является обычной пользовательской функцией.
T_ELLIPSIS...Распаковка, вариативный параметр или создание first-class callable — роль зависит от места.
T_ELSEelseЗапасная ветвь условия.
T_ELSEIFelseifСледующая проверка после неуспешного if.
T_EMPTYemptyПроверка на «пустое» значение по правилам PHP.
T_ENCAPSED_AND_WHITESPACEтекст внутри интерполяцииЛитеральная часть строки с подстановками; несмотря на имя, это не только пробелы.
T_ENDDECLAREenddeclareЗакрывает альтернативную форму declare: ... enddeclare.
T_ENDFORendforЗакрывает альтернативную форму for.
T_ENDFOREACHendforeachЗакрывает альтернативную форму foreach.
T_ENDIFendifЗакрывает альтернативную форму if.
T_ENDSWITCHendswitchЗакрывает альтернативную форму switch.
T_ENDWHILEendwhileЗакрывает альтернативную форму while.
T_ENUMenumPHP 8.1+: начало объявления перечисления.
T_END_HEREDOCзакрывающая меткаКонец heredoc/nowdoc; содержит выбранное в исходнике имя метки.
T_EVALevalКонструкция исполнения PHP-текста. Токенизация сама eval не вызывает.
T_EXITexit, dieЗавершение выполнения; с PHP 8.4 семантика вызова расширена, вид токена сохраняется.
T_EXTENDSextendsУказывает наследование класса или интерфейса.
T_FILE__FILE__Магическая константа пути файла.
T_FINALfinalОграничение переопределения/наследования в соответствующем контексте.
T_FINALLYfinallyЗавершающий блок try: освобождение ресурса независимо от результата.
T_FNfnPHP 7.4+: стрелочная функция.
T_FORforЦикл с явными инициализацией, проверкой и изменением.
T_FOREACHforeachПоследовательный перебор массива/итерируемого объекта.
T_FUNCTIONfunctionОбъявление именованной или анонимной функции.
T_FUNC_C__FUNCTION__Магическая константа имени функции.
T_GLOBALglobalСвязывает локальное имя с глобальной переменной.
T_GOTOgotoПереход к метке с ограничениями области действия.
T_HALT_COMPILER__halt_compilerОстановка компиляции оставшегося текста файла; после неё может находиться полезная нагрузка.
T_IFifУсловный выбор исполнения.
T_IMPLEMENTSimplementsКласс объявляет реализуемые интерфейсы.
T_INC++Увеличение; префиксная и постфиксная формы отличаются результатом выражения.
T_INCLUDEincludeПодключение и выполнение другого PHP-файла.
T_INCLUDE_ONCEinclude_onceПодключение с защитой от повторного включения того же файла.
T_INLINE_HTMLтекст вне PHPОбычный текст/разметка за пределами PHP-тегов; даже похожий на PHP комментарий здесь остаётся текстом.
T_INSTANCEOFinstanceofПроверка принадлежности объекта классу/интерфейсу.
T_INSTEADOFinsteadofВыбор метода при конфликте подключённых трейтов.
T_INTERFACEinterfaceОбъявление интерфейса.
T_INT_CAST(int), (integer)Явное преобразование к целому; не полноценная проверка внешнего ввода.
T_ISSETissetПроверка существования значения, отличного от null.
T_IS_EQUAL==Нестрогое сравнение с правилами преобразования типов.
T_IS_GREATER_OR_EQUAL>=Сравнение «больше либо равно».
T_IS_IDENTICAL===Строгое сравнение значения и типа.
T_IS_NOT_EQUAL!=, <>Нестрогое неравенство.
T_IS_NOT_IDENTICAL!==Отрицание строгой идентичности.
T_IS_SMALLER_OR_EQUAL<=Сравнение «меньше либо равно».
T_LINE__LINE__Магическая константа номера строки.
T_LISTlistДеструктуризация массива в переменные.
T_LNUMBER123, 012, 0x1acЦелочисленная запись разных оснований; отрицательный знак обычно отдельный токен.
T_LOGICAL_ANDandЛогическое И с приоритетом, отличающимся от &&.
T_LOGICAL_ORorЛогическое ИЛИ с приоритетом, отличающимся от двойного вертикального штриха.
T_LOGICAL_XORxorЛогическое исключающее ИЛИ.
T_MATCHmatchPHP 8.0+: выражение выбора со строгим сравнением.
T_METHOD_C__METHOD__Магическая константа имени метода вместе с классом.
T_MINUS_EQUAL-=Вычитание с присваиванием.
T_MOD_EQUAL%=Остаток от деления с присваиванием.
T_MUL_EQUAL*=Умножение с присваиванием.
T_NAMESPACEnamespaceОбъявление пространства имён либо часть относительного обращения.
T_NAME_FULLY_QUALIFIED\App\OrderPHP 8.0+: полное имя с ведущим обратным слешем.
T_NAME_QUALIFIEDApp\OrderPHP 8.0+: составное имя без ведущего обратного слеша.
T_NAME_RELATIVEnamespace\OrderPHP 8.0+: имя относительно текущего namespace.
T_NEWnewСоздание объекта, в том числе анонимного класса.
T_NS_C__NAMESPACE__Магическая константа текущего пространства имён.
T_NS_SEPARATORобратный слешРазделитель пространства имён в контекстах, где не поглощён составным токеном имени.
T_NUM_STRINGиндекс в "$items[0]"Числовой индекс внутри интерполируемой строки. Это не любой числовой литерал программы.
T_OBJECT_CAST(object)Преобразование значения в объект.
T_OBJECT_OPERATOR->Доступ к свойству/методу объекта.
T_NULLSAFE_OBJECT_OPERATOR?->PHP 8.0+: доступ с остановкой цепочки при null.
T_OPEN_TAG<?php, <?Открывающий тег; короткий <? зависит от short_open_tag. Исторический <% удалён в PHP 7.0. Текст токена может включать следующий пробел/перевод строки.
T_OPEN_TAG_WITH_ECHO<?=Открывающий тег с выводом; исторический <%= удалён в PHP 7.0. Отличается от обычного открывающего тега.
T_OR_EQUAL|=Побитовое ИЛИ с присваиванием.
T_PAAMAYIM_NEKUDOTAYIM::Историческое имя токена разрешения области; T_DOUBLE_COLON обозначает то же значение.
T_PIPE|>PHP 8.5+: передача значения в вызываемое выражение оператором pipe.
T_PLUS_EQUAL+=Сложение с присваиванием; для массивов действуют правила объединения ключей.
T_POW**Возведение в степень.
T_POW_EQUAL**=Возведение в степень с присваиванием.
T_PRINTprintВывод одного выражения с возвращаемым значением 1.
T_PRIVATEprivateЗакрытая видимость члена класса.
T_PRIVATE_SETprivate(set)PHP 8.4+: закрытая видимость записи свойства при асимметричной видимости.
T_PROPERTY_C__PROPERTY__PHP 8.4+: имя свойства в контексте hook свойства.
T_PROTECTEDprotectedВидимость члена для класса и связанных с ним наследников.
T_PROTECTED_SETprotected(set)PHP 8.4+: ограничение записи свойства иерархией классов.
T_PUBLICpublicПубличная видимость члена.
T_PUBLIC_SETpublic(set)PHP 8.4+: публичная видимость записи свойства.
T_READONLYreadonlyPHP 8.1+: неизменяемость свойств по правилам readonly; для классов доступна с PHP 8.2.
T_REQUIRErequireОбязательное подключение файла.
T_REQUIRE_ONCErequire_onceОбязательное подключение один раз.
T_RETURNreturnВернуть результат и закончить текущий вызов/подключаемый файл.
T_SL<<Сдвиг битов влево.
T_SL_EQUAL<<=Сдвиг влево с присваиванием.
T_SPACESHIP<=>Трёхзначное сравнение: отрицательный, нулевой или положительный результат.
T_SR>>Сдвиг битов вправо.
T_SR_EQUAL>>=Сдвиг вправо с присваиванием.
T_START_HEREDOC<<<METKAНачало heredoc/nowdoc; открывающая запись включает метку и перевод строки.
T_STATICstaticСтатическое состояние/член либо позднее статическое связывание; нужен контекст.
T_STRINGprice, Order, selfИдентификатор: имя функции, класса, константы и другие роли. Несмотря на название, не означает литерал строки.
T_STRING_CAST(string)Явное преобразование к строке.
T_STRING_VARNAMEимя в ${...}Имя переменной в старой форме строковой интерполяции; не обычный T_VARIABLE с долларом.
T_SWITCHswitchВыбор ветви с семантикой switch.
T_THROWthrowВыброс исключения.
T_TRAITtraitОбъявление набора повторно используемых методов/членов.
T_TRAIT_C__TRAIT__Магическая константа имени трейта.
T_TRYtryНачало области обработки исключений.
T_UNSETunsetУдаление переменной/элемента, а не универсальная очистка всех копий данных.
T_UNSET_CAST(unset)Историческое приведение, удалено в PHP 8.0. Сохраняем в справочнике для понимания старого кода, не используем в новых примерах.
T_USEuseИмпорт имени, подключение трейта или захват переменной замыканием: роли различаются окружением.
T_VARvarИсторическая запись объявления публичного свойства; для нового кода предпочтительна явная видимость.
T_VARIABLE$priceЗапись имени переменной вместе со знаком доллара.
T_VOID_CAST(void)PHP 8.5+: вычислить выражение и отбросить его значение. Это не возвращаемый тип функции void.
T_WHILEwhileУсловие цикла while либо завершающая проверка do...while.
T_WHITESPACEпробел, табуляция, CR/LFПробельный фрагмент исходника. Отступ не равен незначимости при склеивании соседних слов.
T_XOR_EQUAL^=Побитовое исключающее ИЛИ с присваиванием.
T_YIELDyieldПередать значение потребителю генератора и приостановиться.
T_YIELD_FROMyield fromДелегировать перебор другому итерируемому источнику.

К смыслу конструкций: операторы, условия и циклы, строки и интерполяция, функции, объекты. Таблица лексера помогает распознать запись; эти главы учат применять её.

Убрать комментарий, сохранив границы слов

Нужен служебный просмотр исходника без обычных комментариев. Regex легко перепутает // внутри URL со строковым комментарием. Сканер уже различает эти состояния. Однако вырезать комментарий в пустоту опасно: return/* note */7 превратится в return7. В учебном решении сохраняем пробелы на месте непробельных байтов комментария и все переводы строк.

Сохраняем структуру, скрывая комментарий
  1. return/* note */7
  2. T_RETURN, T_COMMENT, T_LNUMBER
  3. Только T_COMMENT заменяется пробелами
  4. Слова не склеились, номера строк сохранились
Скрыть обычный комментарий, не трогая строку и PHPDocСамостоятельный пример
<?php
declare(strict_types=1);

$source = '<?php /** API */ echo "https://shop.test"; /* note */';
$result = '';
foreach (PhpToken::tokenize($source, TOKEN_PARSE) as $token) {
    if ($token->is(T_COMMENT)) {
        $result .= preg_replace('/[^\r\n\t ]/', ' ', $token->text);
    } else {
        $result .= $token->text;
    }
}
var_dump(str_contains($result, 'https://shop.test'));
var_dump(str_contains($result, '/** API */'));
var_dump(!str_contains($result, 'note'));
var_dump(strlen($source) === strlen($result));
Ожидаемый результат
bool(true)
bool(true)
bool(true)
bool(true)

Регулярное выражение здесь работает только внутри уже найденного комментария; оно не пытается разобрать весь PHP. Байтовая длина и переводы строк сохраняются. PHPDoc оставлен намеренно. Это ограниченное преобразование для просмотра, не обещание универсального production-минификатора.

В проекте комментарии могут содержать директивы статического анализатора, лицензию, настройки сборки и аннотации. Их удаление может менять работу инструментов, даже если грамматика PHP осталась корректной. PhpToken::isIgnorable нельзя использовать как кнопку «безопасно удалить всё лишнее».

Практика: отчёт о подавлении ошибок в исходнике

В шаблоне встретился адрес support@shop.test, комментарий с @ и настоящий оператор подавления. Задача — показать только операцию, которую стоит заменить понятной обработкой отказа. Сначала разбираем, затем просматриваем отдельные знаки; ничего не выполняем и не исправляем автоматически.

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

$source = <<<'PHP'
<?php
$email = 'support@shop.test';
// @ is discussed here
@readfile('missing.txt');
PHP;
foreach (PhpToken::tokenize($source, TOKEN_PARSE) as $token) {
    if ($token->is('@')) { echo 'check error handling at line ', $token->line, "\n"; }
}
Ожидаемый результат
check error handling at line 4

Отчёт показывает точное место. Файл missing.txt не читается: это текст для сканера. Следующее действие человека — понять, какой отказ ожидался и как корректно обработать его, а не механически удалить @.

Упражнение: добавьте в исходник строку "@readfile" и ещё один реальный оператор @. Ожидается одно дополнительное сообщение только для оператора. Затем сохраните отчёт с именем файла и номером строки. При показе имени/текста в HTML используйте экранирование; исходник может содержать произвольные теги.

Дальше: ошибки и исключения, чтение файлов, проверка поведения программы.

Все функции и методы Tokenizer

ИнструментПолезное действие
token_get_allРазобрать PHP-текст на массив токенов, не выполняя его.
token_nameПолучить понятное имя T_* по числовому идентификатору.
PhpToken::__constructСоздать один токен вручную для своего преобразователя или отчёта.
PhpToken::getTokenNameПрочитать имя вида токена либо сам одиночный знак.
PhpToken::isПроверить вид или точный текст токена, в том числе по нескольким альтернативам.
PhpToken::isIgnorableУзнать, пропускает ли синтаксический анализатор этот вид токена.
PhpToken::__toStringПолучить исходный текст объекта при преобразовании в строку.
PhpToken::tokenizeРазобрать исходник в однородный список объектов с текстом и позицией.

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

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

token_get_allРазобрать PHP-текст на массив токенов, не выполняя его.

PHP 4.2+ · tokenizer

token_get_all(string $code, int $flags = 0): array

Разобрать PHP-текст на массив токенов, не выполняя его.

Токен — кусочек исходного текста с назначением: имя переменной, число, слово echo или знак ;. Лексический анализатор разбивает текст, но не запускает этот код. В примерах строка '<?php echo 7;' — данные для анализатора. Само число 7 он не выводит. $tokens хранит полученный список; foreach по очереди рассматривает его элементы.

Вариант с объектами хранит каждый кусочек в PhpToken: ->text читает текст, ->is(...) задаёт вопрос о его виде. ::tokenize(...) вызывается у класса и создаёт список объектов. Основа синтаксиса: переменные, массивы, перебор, классы и объекты.

Часть вызоваЧто она означает
codeИсходный текст, обычно вместе с открывающим тегом <?php. Без тега текст считается находящимся вне PHP.
flags0: лексический разбор; TOKEN_PARSE: учитывать синтаксический контекст, в том числе допустимые зарезервированные слова. Некорректная грамматика в этом режиме вызывает ParseError.
РезультатМассив. Элемент — либо строка с отдельным знаком, либо [идентификатор, исходный текст, номер начальной строки]. Строки считаются с 1.
ГраницыЭто не AST, не выполнение и не проверка безопасности программы. Сканер использует грамматику установленной версии PHP.
Одна строка превращается в разные элементы
  1. <?php echo 7; — входная строка
  2. [T_OPEN_TAG, "<?php ", 1]
  3. [T_ECHO, "echo", 1], пробел, число
  4. Знак ; остаётся отдельной строкой
Увидеть имена токенов и отдельный знакСамостоятельный пример
<?php
declare(strict_types=1);

$tokens = token_get_all('<?php echo 7;');
foreach ($tokens as $token) {
    echo is_array($token) ? token_name($token[0]) : $token;
    echo "\n";
}
Ожидаемый результат
T_OPEN_TAG
T_ECHO
T_WHITESPACE
T_LNUMBER
;

Сначала проверяем is_array: обращение к [0] имеет разный смысл у массива и строки. Имена T_* позволяют читать результат без запоминания числовых кодов. echo внутри анализируемой строки не выполнялся.

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

$template = '<h1>Shop</h1><?php echo 7; ?>Done';
foreach (token_get_all($template) as $token) {
    if (is_array($token) && $token[0] === T_INLINE_HTML) {
        echo $token[1], "\n";
    }
}
Ожидаемый результат
<h1>Shop</h1>
Done

Так редактор шаблона отделяет HTML-части от PHP. Это не HTML-парсер: найденный текст ещё можно разобрать соответствующим инструментом. При показе исходника на сайте его экранируют, иначе браузер воспримет теги.

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

$source = '<?php class Delivery { const PUBLIC = 1; }';
foreach ([0, TOKEN_PARSE] as $flags) {
    foreach (token_get_all($source, $flags) as $token) {
        if (is_array($token) && $token[1] === 'PUBLIC') {
            echo token_name($token[0]), "\n";
        }
    }
}
Ожидаемый результат
T_PUBLIC
T_STRING

PUBLIC здесь имя константы, хотя отдельно public является ключевым словом. Грамматический контекст помогает понять разрешённую роль слова; сам текст остаётся прежним.

Частая ошибка — передать /* note */ без открывающего тега и ждать T_COMMENT: получится T_INLINE_HTML. Пробел или перевод строки после открывающего тега может входить в текст T_OPEN_TAG. Нельзя восстанавливать исходник по одним именам токенов: нужны их исходные тексты. Для больших файлов список занимает дополнительную память; ограничьте размер анализируемых входов.

Связанные инструменты: PhpToken::tokenize; token_name.

token_nameПолучить понятное имя T_* по числовому идентификатору.

PHP 4.2+ · tokenizer

token_name(int $id): string

Получить понятное имя T_* по числовому идентификатору.

Токен — кусочек исходного текста с назначением: имя переменной, число, слово echo или знак ;. Лексический анализатор разбивает текст, но не запускает этот код. В примерах строка '<?php echo 7;' — данные для анализатора. Само число 7 он не выводит. $tokens хранит полученный список; foreach по очереди рассматривает его элементы.

Вариант с объектами хранит каждый кусочек в PhpToken: ->text читает текст, ->is(...) задаёт вопрос о его виде. ::tokenize(...) вызывается у класса и создаёт список объектов. Основа синтаксиса: переменные, массивы, перебор, классы и объекты.

Часть вызоваЧто она означает
idЧисловой ID из токена или именованная константа вроде T_VARIABLE. Не сохраняйте «магическое» число из чужой версии PHP.
РезультатИмя известного токена. Для неизвестного ID возвращается строка UNKNOWN, а не false/null.
Обычные знакиУ ; или + нет такого T_*-имени. Эта функция не заменяет chr; объектный getTokenName умеет вернуть одиночный знак.
ID становится подписью в отчёте
  1. ID токена T_VARIABLE
  2. token_name(ID)
  3. Строка T_VARIABLE
  4. В отчёте видно назначение элемента
Подписать вид переменнойСамостоятельный пример
<?php
declare(strict_types=1);

echo token_name(T_VARIABLE), "\n";
echo token_name(-1), "\n";
Ожидаемый результат
T_VARIABLE
UNKNOWN

UNKNOWN — нормальный ответ для неизвестного числа. Значение ID не обязано сохраняться между версиями PHP, поэтому в правилах анализатора используют T_VARIABLE, а в переносимом отчёте сохраняют его имя.

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

$source = "<?php\necho 7;\nprint 8;";
foreach (token_get_all($source) as $token) {
    if (is_array($token) && in_array($token[0], [T_ECHO, T_PRINT], true)) {
        echo 'line ', $token[2], ': ', token_name($token[0]), "\n";
    }
}
Ожидаемый результат
line 2: T_ECHO
line 3: T_PRINT

Так можно составить список мест, где шаблон пишет ответ. Наличие echo не является ошибкой само по себе: правило зависит от роли файла. Лексер не знает, должен ли данный файл быть шаблоном или сервисом.

Связанные инструменты: PhpToken::getTokenName; token_get_all.

PhpToken::__constructСоздать один токен вручную для своего преобразователя или отчёта.

PHP 8.0+ · tokenizer

final public PhpToken::__construct(int $id, string $text, int $line = -1, int $pos = -1)

Создать один токен вручную для своего преобразователя или отчёта.

Токен — кусочек исходного текста с назначением: имя переменной, число, слово echo или знак ;. Лексический анализатор разбивает текст, но не запускает этот код. В примерах строка '<?php echo 7;' — данные для анализатора. Само число 7 он не выводит. $tokens хранит полученный список; foreach по очереди рассматривает его элементы.

Вариант с объектами хранит каждый кусочек в PhpToken: ->text читает текст, ->is(...) задаёт вопрос о его виде. ::tokenize(...) вызывается у класса и создаёт список объектов. Основа синтаксиса: переменные, массивы, перебор, классы и объекты.

Часть вызоваЧто она означает
idИменованная константа T_* либо код отдельного знака (например ord(";")).
textБуквальный текст токена. Он не исполняется и не проверяется на соответствие ID.
lineНачальная строка с 1, если известна. -1 обозначает неизвестное положение.
posСмещение в байтах от начала исходника с 0. -1 — неизвестно; это не номер Unicode-символа.
Возвратnew возвращает созданный объект. Конструктор final: наследник не может его переопределить.
Ручная карточка элемента
  1. T_VARIABLE задаёт вид
  2. Текст $price задаёт содержимое
  3. Строка 2, байт 6 задают положение
  4. Объект хранит четыре независимых значения
Собрать запись для имени переменнойСамостоятельный пример
<?php
declare(strict_types=1);

$token = new PhpToken(T_VARIABLE, '$price', 2, 6);
echo $token->getTokenName(), ': ', $token->text, "\n";
echo $token->line, '/', $token->pos, "\n";
Ожидаемый результат
T_VARIABLE: $price
2/6

new создаёт объект; параметры описывают его поля. $price находится внутри одинарных кавычек, поэтому это текст имени, а не чтение переменной программы.

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

$inserted = [new PhpToken(ord(';'), ';'), new PhpToken(T_WHITESPACE, "\n")];
foreach ($inserted as $token) {
    echo $token->text;
}
echo $inserted[0]->line, '/', $inserted[0]->pos, "\n";
Ожидаемый результат
;
-1/-1

У новых элементов нет исходной позиции. Если меняете исходник, прежние позиции остальных токенов автоматически не пересчитываются; после изменения можно снова токенизировать результат.

Конструктор разрешит несогласованные поля, например ID T_ECHO и текст price. Это описание, которое передал автор, а не доказательство корректного синтаксиса. Для чтения настоящего исходника используйте PhpToken::tokenize.

Связанные инструменты: PhpToken::tokenize; PhpToken::getTokenName.

PhpToken::getTokenNameПрочитать имя вида токена либо сам одиночный знак.

PHP 8.0+ · tokenizer

public PhpToken::getTokenName(): ?string

Прочитать имя вида токена либо сам одиночный знак.

Токен — кусочек исходного текста с назначением: имя переменной, число, слово echo или знак ;. Лексический анализатор разбивает текст, но не запускает этот код. В примерах строка '<?php echo 7;' — данные для анализатора. Само число 7 он не выводит. $tokens хранит полученный список; foreach по очереди рассматривает его элементы.

Вариант с объектами хранит каждый кусочек в PhpToken: ->text читает текст, ->is(...) задаёт вопрос о его виде. ::tokenize(...) вызывается у класса и создаёт список объектов. Основа синтаксиса: переменные, массивы, перебор, классы и объекты.

Часть вызоваЧто она означает
ПараметрыНет: метод читает id текущего объекта.
РезультатИмя T_*, одиночный символ для ID меньше 256 или null для неизвестного ID от 256. Передавайте настоящие ID сканера: отрицательный вручную заданный ID тоже попадает в байтовую ветку реализации.
Отличие от token_nameПроцедурная функция отдаёт UNKNOWN для неизвестного ID; этот метод отдаёт null. Текст токена читается отдельно через text.
Один интерфейс для разных элементов
  1. ID T_ECHO → T_ECHO
  2. ID ord(";") → ;
  3. Неизвестный ID → null
  4. text всё ещё содержит конкретный исходный текст
Не путать имя вида с текстомСамостоятельный пример
<?php
declare(strict_types=1);

$token = new PhpToken(T_VARIABLE, '$quantity');
echo $token->getTokenName(), "\n", $token->text, "\n";
Ожидаемый результат
T_VARIABLE
$quantity

Первое значение сообщает, что перед нами переменная; второе — какая именно запись встретилась. Это полезно для списка переменных в редакторе.

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

foreach ([new PhpToken(ord(';'), ';'), new PhpToken(PHP_INT_MAX, '?')] as $token) {
    echo $token->getTokenName() ?? 'unknown token', "\n";
}
Ожидаемый результат
;
unknown token

Оператор ?? выбирает подпись, когда слева null. Он не изменяет сам объект и не делает неизвестный элемент корректным PHP-кодом.

Связанные инструменты: token_name; PhpToken::is.

PhpToken::isПроверить вид или точный текст токена, в том числе по нескольким альтернативам.

PHP 8.0+ · tokenizer

public PhpToken::is(int|string|array $kind): bool

Проверить вид или точный текст токена, в том числе по нескольким альтернативам.

Токен — кусочек исходного текста с назначением: имя переменной, число, слово echo или знак ;. Лексический анализатор разбивает текст, но не запускает этот код. В примерах строка '<?php echo 7;' — данные для анализатора. Само число 7 он не выводит. $tokens хранит полученный список; foreach по очереди рассматривает его элементы.

Вариант с объектами хранит каждый кусочек в PhpToken: ->text читает текст, ->is(...) задаёт вопрос о его виде. ::tokenize(...) вызывается у класса и создаёт список объектов. Основа синтаксиса: переменные, массивы, перебор, классы и объекты.

Часть вызоваЧто она означает
kind как intСравнить с id, например T_FUNCTION.
kind как stringСравнить буквально с text, с учётом регистра. Строка "T_FUNCTION" не обозначает константу.
kind как arrayСписок int/string: достаточно первого совпадения. Пустой список даёт false; неверный тип достигнутого элемента приводит к TypeError.
Результатtrue/false. Метод ничего не переименовывает и не изменяет.
Что именно сравниваем
  1. Токен: ID T_ECHO, text ECHO
  2. is(T_ECHO) → true
  3. is("echo") → false
  4. is([T_PRINT, T_ECHO]) → true
Отличить регистр текста от вида ключевого словаСамостоятельный пример
<?php
declare(strict_types=1);

$token = PhpToken::tokenize('<?php ECHO 7;')[1];
var_dump($token->is(T_ECHO), $token->is('echo'), $token->is([T_PRINT, T_ECHO]));
Ожидаемый результат
bool(true)
bool(false)
bool(true)

PHP распознаёт ECHO как ключевое слово, но сохраняет исходные заглавные буквы. Проверка вида подходит для анализа; проверка текста — для точной правки.

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

$source = '<?php interface Clock {} trait Logged {} class Order {}';
foreach (PhpToken::tokenize($source, TOKEN_PARSE) as $token) {
    if ($token->is([T_INTERFACE, T_TRAIT, T_CLASS])) {
        echo $token->text, "\n";
    }
}
Ожидаемый результат
interface
trait
class

Это поиск слов объявления. Для полноценного каталога имён надо учитывать контекст: ::class, анонимные классы, namespace и вложенные конструкции. Одно условие не превращается в полный синтаксический анализатор.

Массив альтернатив должен целиком состоять из int/string. Не полагайтесь на короткое замыкание, при котором ошибочный элемент после совпадения случайно не рассматривается. Валидация собственного набора правил выполняется при его создании.

Связанные инструменты: PhpToken::getTokenName; PhpToken::isIgnorable.

PhpToken::isIgnorableУзнать, пропускает ли синтаксический анализатор этот вид токена.

PHP 8.0+ · tokenizer

public PhpToken::isIgnorable(): bool

Узнать, пропускает ли синтаксический анализатор этот вид токена.

Токен — кусочек исходного текста с назначением: имя переменной, число, слово echo или знак ;. Лексический анализатор разбивает текст, но не запускает этот код. В примерах строка '<?php echo 7;' — данные для анализатора. Само число 7 он не выводит. $tokens хранит полученный список; foreach по очереди рассматривает его элементы.

Вариант с объектами хранит каждый кусочек в PhpToken: ->text читает текст, ->is(...) задаёт вопрос о его виде. ::tokenize(...) вызывается у класса и создаёт список объектов. Основа синтаксиса: переменные, массивы, перебор, классы и объекты.

Часть вызоваЧто она означает
ПараметрыНет. Решение принимается по id.
trueT_WHITESPACE, T_COMMENT, T_DOC_COMMENT и T_OPEN_TAG в PHP 8.5.11.
falseВ том числе T_CLOSE_TAG, T_OPEN_TAG_WITH_ECHO и T_INLINE_HTML: эти элементы имеют иной смысл.
Ограничение«Пропускается парсером» не означает «можно безопасно вырезать из файла». Пробел разделяет слова; открывающий тег включает PHP; PHPDoc могут читать инструменты.
Список значимых элементов для отчёта
  1. Сканер сохранил тег, комментарий и пробелы
  2. isIgnorable задаёт фильтр отчёта
  3. echo, число и ; остаются видимыми
  4. Оригинальный файл сохраняем целиком
Показать только значимые для грамматики элементыСамостоятельный пример
<?php
declare(strict_types=1);

foreach (PhpToken::tokenize('<?php /* price */ echo 7;') as $token) {
    if (!$token->isIgnorable()) { echo $token->text, "\n"; }
}
Ожидаемый результат
echo
7
;

Такой список помогает объяснить структуру выражения. Его нельзя склеивать и использовать как исходный файл: без тега PHP и разделителей поведение изменится.

Отдельно считать документацию, даже если парсер её пропускаетСамостоятельный пример
<?php
declare(strict_types=1);

$source = '<?php /** Price in kopecks. */ function price() { return 7; }';
$documents = 0;
foreach (PhpToken::tokenize($source) as $token) {
    if ($token->is(T_DOC_COMMENT)) { $documents++; }
}
echo 'documentation blocks: ', $documents, "\n";
var_dump((new PhpToken(T_OPEN_TAG, '<?php '))->isIgnorable());
Ожидаемый результат
documentation blocks: 1
bool(true)

Документационные комментарии нужны IDE, генераторам справки и некоторым библиотекам. Их удаление — отдельное решение для конкретного проекта, а не автоматическая оптимизация.

Связанные инструменты: PhpToken::is; PhpToken::__toString.

PhpToken::__toStringПолучить исходный текст объекта при преобразовании в строку.

PHP 8.0+ · tokenizer

public PhpToken::__toString(): string

Получить исходный текст объекта при преобразовании в строку.

Токен — кусочек исходного текста с назначением: имя переменной, число, слово echo или знак ;. Лексический анализатор разбивает текст, но не запускает этот код. В примерах строка '<?php echo 7;' — данные для анализатора. Само число 7 он не выводит. $tokens хранит полученный список; foreach по очереди рассматривает его элементы.

Вариант с объектами хранит каждый кусочек в PhpToken: ->text читает текст, ->is(...) задаёт вопрос о его виде. ::tokenize(...) вызывается у класса и создаёт список объектов. Основа синтаксиса: переменные, массивы, перебор, классы и объекты.

Часть вызоваЧто она означает
ВызовОбычно (string) $token, echo $token или конкатенация; напрямую вызывать метод обычно незачем.
РезультатСодержимое публичного свойства text. Ничего не исполняется, не переводится в HTML и не очищается.
StringablePhpToken реализует Stringable. Возможность получить строку не означает автоматическое принятие объекта всеми строгими string-параметрами; явное приведение убирает двусмысленность.
Обратный путь к исходнику
  1. Объекты сохранили каждый кусочек текста
  2. (string) $token читает text
  3. Склеиваем в первоначальном порядке
  4. Получаем ту же строку исходного кода
Получить текст без выполненияСамостоятельный пример
<?php
declare(strict_types=1);

$token = new PhpToken(T_VARIABLE, '$total');
echo (string) $token, "\n";
Ожидаемый результат
$total

Выводится запись $total, а не значение переменной с таким именем. Токен не ссылается на переменные исполняющей программы.

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

$source = "<h1>Shop</h1><?php\n// note\necho 7; ?>";
$restored = '';
foreach (PhpToken::tokenize($source) as $token) { $restored .= (string) $token; }
var_dump($restored === $source);
Ожидаемый результат
bool(true)

Сохраняются не только команды, но и оформление. Позиции имеют смысл относительно этой исходной строки. Для подсветки на веб-странице дополнительно используйте htmlspecialchars, чтобы исходник не стал исполняемой HTML-разметкой.

Связанные инструменты: PhpToken::tokenize; PhpToken::isIgnorable.

PhpToken::tokenizeРазобрать исходник в однородный список объектов с текстом и позицией.

PHP 8.0+ · tokenizer

public static PhpToken::tokenize(string $code, int $flags = 0): array

Разобрать исходник в однородный список объектов с текстом и позицией.

Токен — кусочек исходного текста с назначением: имя переменной, число, слово echo или знак ;. Лексический анализатор разбивает текст, но не запускает этот код. В примерах строка '<?php echo 7;' — данные для анализатора. Само число 7 он не выводит. $tokens хранит полученный список; foreach по очереди рассматривает его элементы.

Вариант с объектами хранит каждый кусочек в PhpToken: ->text читает текст, ->is(...) задаёт вопрос о его виде. ::tokenize(...) вызывается у класса и создаёт список объектов. Основа синтаксиса: переменные, массивы, перебор, классы и объекты.

Часть вызоваЧто она означает
codeИсходный PHP/HTML-текст, включая теги. Без <?php анализ начинается вне PHP.
flags0 либо TOKEN_PARSE для учёта грамматики. При синтаксической ошибке TOKEN_PARSE может выбросить ParseError.
РезультатСписок PhpToken; при вызове у наследника — объекты этого наследника (static[]). Все элементы имеют id, text, line и pos, в том числе знаки пунктуации.
СтоимостьВесь список хранится в памяти. Не загружайте неограниченные присланные файлы; лексер не анализирует семантику приложения.
От кода к точному месту сообщения
  1. Вход <?php $price = 7;
  2. Токен $price имеет T_VARIABLE
  3. line = 1, pos = 6
  4. Редактор отмечает байты этой переменной
Найти положение переменной в исходникеСамостоятельный пример
<?php
declare(strict_types=1);

foreach (PhpToken::tokenize('<?php $price = 7;') as $token) {
    if ($token->is(T_VARIABLE)) {
        echo $token->text, ': line ', $token->line, ', byte ', $token->pos, "\n";
    }
}
Ожидаемый результат
$price: line 1, byte 6

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

Получить понятную реакцию на незаконченный PHP-кодСамостоятельный пример
<?php
declare(strict_types=1);

try {
    PhpToken::tokenize('<?php if (', TOKEN_PARSE);
    echo "accepted\n";
} catch (ParseError $error) {
    echo "syntax error\n";
}
Ожидаемый результат
syntax error

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

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

class ProjectToken extends PhpToken {
    public function isOutput(): bool { return $this->is([T_ECHO, T_PRINT]); }
}
$count = 0;
foreach (ProjectToken::tokenize('<?php echo 7; print 8;') as $token) {
    if ($token->isOutput()) { $count++; }
}
echo $count, "\n";
Ожидаемый результат
2

Объекты результата — ProjectToken. Метод прячет повторяющийся вопрос в одном месте. Конструктор PhpToken final; дополнительные свойства наследника требуют понятных значений по умолчанию, а не расчёта в переопределённом конструкторе.

T_STRING — вид идентификатора, а не гарантия, что найден вызов функции. Класс, имя метода, константа и другие конструкции тоже могут иметь такой токен. Для разрешения имён, типов и безопасного изменения программы нужен анализ контекста, а для сложных преобразований — AST и соответствующая библиотека.

Связанные инструменты: token_get_all; PhpToken::__construct; PhpToken::is.

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

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

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

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

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