#php #error-handling #tokenize
#php #обработка ошибок #маркировать
Вопрос:
Функция PHPs token_get_all
(которая позволяет преобразовывать исходный код PHP в токены) может выдавать две ошибки: одну, если встречается многострочный комментарий без обработки, другую, если обнаружен неожиданный символ.
Я хотел бы перехватить эти ошибки и выдать их как исключения.
Проблема в том, что, поскольку эти ошибки являются ошибками синтаксического анализа, они не могут быть обработаны с помощью функции обработки ошибок, которую вы обычно указываете с помощью set_error_handler
.
В настоящее время я реализовал следующее:
// Reset the error message in error_get_last()
@$errorGetLastResetUndefinedVariable;
$this->tokens = @token_get_all($code);
$error = error_get_last();
if (preg_match(
'~^(Unterminated comment) starting line ([0-9] )$~',
$error['message'],
$matches
)
) {
throw new ParseErrorException($matches[1], $matches[2]);
}
if (preg_match(
'~^(Unexpected character in input:s '(.)' (ASCII=[0-9] ))~s',
$error['message'],
$matches
)
) {
throw new ParseErrorException($matches[1]);
}
Должно быть очевидно, что я не очень рад использовать это решение. Особенно тот факт, что я сбрасываю сообщение об ошибке в error_get_last
при доступе к неопределенной переменной, кажется довольно неудовлетворительным.
Итак: есть ли лучшее решение этой проблемы?
Ответ №1:
Установите пользовательский обработчик ошибок с помощью set_error_handler
. Вызов token_get_all
. Затем отключите обработчик ошибок, вызвав restore_error_handler
.
Это позволит вам перехватывать предупреждения. Убедитесь, что вы удалили @
подавитель. Вы можете, например, зарегистрировать обработчик ошибок, который находится в классе, который будет просто записывать любые предупреждения для последующей проверки.
Непроверенный пример кода:
class CatchWarnings {
private $warnings = array();
public function handler($errno, $errstr, $errfile, $errline) {
switch ($errno) {
case E_USER_WARNING:
$this->warnings[] = $errstr;
return true; // cancel error handling bubble
}
return false; // error handling as usual
}
public function has_warnings() {
return count($this->warnings) > 0;
}
}
$cw = new CatchWarnings();
set_error_handler(array($cw, "handler"));
token_get_all();
restore_error_handler();
Обычно проверка и выполнение — это две разные вещи, но, похоже, нет способа проверить / удалить фрагмент PHP-кода (во всяком случае, с 5.x).
Комментарии:
1. К сожалению, это не работает (как я уже упоминал в вопросе):
token_get_all
выдаетE_COMPILE_WARNING
, и это один из типов ошибок, которые не могут быть перехвачены обработчиком ошибок : (2. Глядя на это php.net/manual/en/errorfunc.constants.php Я бы сделал вывод, что вы можете перехватывать
E_COMPILE_WARNING
, вы уверены, что установили правильныйerror_reporting
уровень?3. К сожалению, согласно
set_error_handler()
документацииE_ERROR
(хотя и относящейся к совершенно другой версии PHP, чем когда был задан этот вопрос), определяемые пользователем обработчики ошибок не могут обрабатыватьE_PARSE
,E_CORE_ERROR
E_CORE_WARNING
,E_COMPILE_ERROR
E_COMPILE_WARNING
E_STRICT
, ,, или большую часть из,,,,,,,,,,,,,,,,,,,.