Почему PHP set_execption_handler захватывает объект ошибки - PullRequest
0 голосов
/ 07 августа 2020

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

Вот PHP:

<?php
    set_error_handler(function() {
        echo 'error';
    });
    set_exception_handler(function() {
        echo 'exception';
        $args = func_get_args();
        print_r($args);
    });
    $obj = new stdClass;
    $obj->jdhgdfkjh();
    exit(0);

Вот результат:


exceptionArray
(
    [0] => Error Object
        (
            [message:protected] => Call to undefined method stdClass::jdhgdfkjh()
            [string:Error:private] => 
            [code:protected] => 0
            [file:protected] => /var/www/domain.com/index.php
            [line:protected] => 11
            [trace:Error:private] => Array
                (
                )

            [previous:Error:private] => 
        )

)

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

Хотелось бы некоторой ясности, если бы кто-нибудь сталкивался с этим раньше.

1 Ответ

1 голос
/ 07 августа 2020

Постараюсь ответить на свой вопрос. @apokryfos прав: в руководстве есть подробности об этом. Меня немного сбивает с толку то, что set_exception_handler захватывает не только объекты Exception и Throwable, но также объекты Error (которые являются объектами Throwable, но не объектами Exception).

Меня это сбивает с толку, потому что в set_error_handler есть слово «ошибка», но он не улавливает эти типы объектов.

Итак, для всех, кто наткнется на это, в новых версиях PHP, вы не можете ожидать объект Exception для обратного вызова set_exception_handler. Вам нужно ожидать Throwable, и нелинейно вы также можете получить Error объектов, которые не получены set_error_handler.

Чтобы справиться с этим в моем собственная настройка, у меня есть следующее set_error_handler, чтобы сделать вещи немного чище:

set_error_handler(function($errno, $errstr, $errfile, $errline, $errcontext) {
    $args = array($errstr, $errno, E_ERROR, $errfile, $errline);
    $errorException = new \ErrorException(... $args);
});

Это затем будет перехвачено вашим обратным вызовом set_exception_handler. Надеюсь, это поможет другим :)

...