PHP Try Catch для всего класса


Простой вопрос, но, кажется, не может найти ответ.

Если у меня есть класс php, можно ли зарегистрировать обработчик исключений для всего класса?

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

Поэтому я хотел бы иметь одну область в моем классе, которая ловит любое число исключений, определенных мной из моей модели домена, и выдает их как более общее исключение, например

В настоящее время я делаю это путем обертывания вызовов методов к объектам домена в блоке try catch. Это становится очень запутанным, поскольку я использую все больше и больше объектов домена и их методов. Было бы здорово удалить эти блоки try catch и обработать их все на одном месте в классе т. е. если в классе возникает какое-либо исключение, оно перехватывается одним обработчиком событий, определенным в классе

2 8

2 ответа:

Вы можете использовать прокси-класс для выполнения вызовов от вашего имени и позволить вам обернуть исключение:

class GenericProxy
{
    private $obj;
    private $handler;

    public function __construct($target, callable $exceptionHandler = null)
    {
        $this->obj = $target;
        $this->handler = $exceptionHandler;
    }

    public function __call($method, $arguments)
    {
        try {
            return call_user_func_array([$this->obj, $method], $arguments);
        } catch (Exception $e) {
            // catch all
            if ($this->handler) {
                throw call_user_func($this->handler, $e);
            } else {
                throw $e;
            }
        }
    }
}

$proxy = new GenericProxy($something, function(Exception $e) {
    return new MyCoolException($e->getMessage(), $e->getCode(), $e);
});
echo $proxy->whatever_method($foo, $bar);
Он использует магический метод __call() для перехвата и пересылки вызовов метода к цели.

EDIT: похоже, что это плохая идея, так как " set_exception_handler-это глобальный метод. Может закончиться целым миром проблем, если множество классов установят себя в качестве глобального обработчика". Спасибо @Gaz_Edge за указание на это.

Вместо этого вам следует посмотреть на ответ Джека .

Если я понял, что вы хотите, я думаю, что вы можете использовать set_exception_handler в своем классе.

Пример:

class myClass {
    public function __construct() {
        set_exception_handler(array('myClass','exception_handler'));
    }

    public function test(){
        $mySecondClass = new mySecondClass();
    }

    public static function exception_handler($e) {
        print "Exception caught in myClass: ". $e->getMessage() ."\n";
    }
}

class mySecondClass{
    public function __construct() {
        throw new Exception('Exception in mySecondClass');
    }
}

$myClass = new myClass();
$myClass->test();

Что бы дать : Exception caught in myClass: Exception in mySecondClass

Таким образом, это будет выводить исключение второго класса, обработанное вашим первым обработчиком класса.

Надеюсь, это поможет !