Как получить правильный номер строки при использовании trigger_error в PHP? - PullRequest
1 голос
/ 09 октября 2008

Я использую trigger_error, чтобы «выбросить» ошибки в пользовательский класс. Моя проблема в том, что trigger_error печатает номер строки, где вызывался trigger_error. Например, учитывая следующий код:

01    <?php
02        class Test {
03            function doAction() {
04                $this->doSubAction();
05            }
06            
07            function doSubAction() {
08                if(true)
09                    trigger_error('Custom error', E_USER_WARNING);
10            }
11        }
12        
13        $var = new Test();
14        $var->doAction();
15    ?>

PHP распечатает следующее:

Предупреждение: Настраиваемая ошибка в test.php в строке 9

Как бы вы заставили PHP вернуть строку, где была вызвана функция doAction () (метод, вызываемый вне класса, игнорируя все внутренние вызовы), следующим образом?

Предупреждение: Настраиваемая ошибка в test.php on line 14

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

Ответы [ 5 ]

2 голосов
/ 09 октября 2008

Лучше всего настроить обработчик ошибок, который показывает полную трассировку стека.

Установите пользовательский обработчик ошибок и вызовите в нем debug_print_backtrace (). Вы найдете это полезным в целом, а также в этом конкретном случае.

0 голосов
/ 10 февраля 2016

Я подумал, что брошу свои два цента в банк и расскажу, что я обычно использую, как есть, или с небольшими настройками для библиотек PHP, которые я создаю и которые часто используются другими разработчиками.

Я подразделяю ошибки, которые могут возникнуть при выполнении программы, на две категории: те, которые являются результатом ошибочного программирования, и те, которые возникают из-за ошибки пользователя или какого-либо внешнего фактора. В первом случае я использую trigger_error в сочетании с E_USER_ERROR, а во втором - Исключение, в частности, Исключение пакета, которое затем наследуется всеми другими Исключениями в библиотеке.

Примером ошибки при разработке может быть передача целого числа в параметре, который, как ожидается, будет строкой (до V7), или доступ к методу или свойству класса, который не существует. (Вы можете использовать здесь свое собственное воображение разработчика.) Очевидно, что другому разработчику не нужно заботиться о том, что ошибка была сгенерирована глубоко в недрах оператора __get или __set или какой-то другой магической конструкции, а скорее они захотят узнать в частности, где их ошибка. Посмотрим правде в глаза ... разработчики не любят пробираться через след.

Таким образом, метод, с помощью которого я локализую сообщение об ошибке, просто:

function localize_error_msg($msg, $level) {
    $level = (int)$level;
    $backtrace = debug_backtrace(DEBUG_BACKTRACE_IGNORE_ARGS, $level + 1)[$level];
    return $msg . " in " . $backtrace['file'] . " on line " . $backtrace['line'];
}

Я передаю уровень обратной трассировки, который зависит от используемой конструкции, которая обычно равна 1 или 2, а остальное не требует пояснений.

Чтобы предотвратить повторяющуюся последовательность «в файле в строке n», я добавляю этот обработчик ошибок:

set_error_handler(function($errno, $errstr, $errfile, $errline) {
    if (preg_match('/on line \d+$/', $errstr) === 1)
        die($errstr);
    else return false;
}, E_USER_ERROR | E_USER_WARNING | E_USER_NOTICE);

Опять же, мне нравится быть простым. Можно утверждать, что локализация сообщения об ошибке должна происходить в обработчике, но тогда вы должны иметь возможность проходить в глубину, которая теперь составляет еще 2 уровня глубоко внутри обработчика, и, ну, после что.

Счастливые тропы!

0 голосов
/ 17 июля 2009

Хорошо, для тех из вас, кто интересуется моим окончательным решением, я включил в нашу структуру следующий фрагмент кода, который возвращает правильный номер строки во всех случаях, которые мы могли протестировать. Мы используем его в производстве.

ErrorHandler класс

Ловит необработанные исключения PHP, ошибки PHP и PEAR::Error s. Вам нужно будет немного его изменить, если в коде есть некоторые специфичные для фреймворка функции, но их не должно быть сложно отследить. Наслаждайтесь!

0 голосов
/ 09 октября 2008

Обычно я также помещаю туда trigger_error (). Это гарантирует, что я точно знаю, где он вызван и где именно произошла ошибка. Затем я отправляю все ошибки себе по электронной почте, когда в работе. Я знаю, что это не автоматически, но, по крайней мере, вы можете проследить, что произошло.

0 голосов
/ 09 октября 2008

Два варианта, ни один не особенно приятен на вкус:

  • Переопределение. У test () есть аргументы __LINE__ (например, "test(__LINE__)" и аргумент для trigger_error). Установите обработчик ошибок для печати настраиваемого сообщения об ошибке. ПРИМЕЧАНИЕ: Это ужасно безобразно. : -)

  • Установите обработчик ошибок, и пусть он вызывает и обрабатывает ужасающе большой вывод debug_backtrace (). Эта функция может быть полезна при отладке ... Но то, что вы пытаетесь сделать, излишне. Пожалуйста, не используйте эту функцию как часть обычной работы системы.

Краткий ответ: слишком сложно, не пытайся. : - |

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...