Установка обработчиков исключений по умолчанию в базовом классе - хорошо или плохо - PullRequest
2 голосов
/ 30 марта 2011

Итак, у меня есть простой базовый класс для сервера - и я понял, что для ряда исключений, которые я выбрасываю, обработка будет достаточно согласованной для всех типов серверов (например, ошибки HTTP 4xx).

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

Класс сервера:

<?php

abstract class Server
{
    protected $methodsAllowed = array('POST', 'GET');
    protected $requiredParameters = array();

    protected function isMethodAllowed()
    {
        if (!isset($_SERVER['REQUEST_METHOD'])) {
            $_SERVER['REQUEST_METHOD'] = 'CLI';
        }

        if (!in_array($_SERVER['REQUEST_METHOD'], $this->methodsAllowed)) {
            throw new Exception_Server_MethodNotAllowed($_SERVER['REQUEST_METHOD'], $this->methodsAllowed);
        }
    }

    protected function areParametersCorrect()
    {
        foreach ($this->requiredParameters as $parameter) {
            if (!in_array($parameter, array_keys($_REQUEST))) {
                throw new Exception_Server_MissingParameter('Missing parameter "' . $parameter . '" in request');
            }
        }
    }

    protected function init()
    {
        $this->isMethodAllowed();
        $this->areParametersCorrect();
    }

    protected function sendXML($xml)
    {
        header('Content-Type: text/xml');
        echo $xml;
        exit;
    }

    abstract public function respond();

    public static function exceptionHandler($exception)
    {
        switch (true) {
            case $exception instanceof Exception_HTTP_400:
                error_log($exception->getMessage());
                header('HTTP/1.1 400 Not Found');
                exit;

            case $exception instanceof Exception_HTTP_404:
                error_log($exception->getMessage());
                header('HTTP/1.1 404 Not Found');
                exit;

            case $exception instanceof Exception_HTTP_405:
                error_log($exception->getMessage());
                header('HTTP/1.1 405 Method Not Allowed');
                header('Allow: ' . implode(', ', $exception->getMethodsAllowed()));
                exit;
        }
    }
}

Exception_Handler::register('Server_Factory::exceptionHandler');

class Exception_Server_MethodNotAllowed extends Exception_HTTP_405 { }
class Exception_Server_MissingParameter extends Exception_HTTP_400 { }

Обработчик по умолчанию:

class Exception_Handler
{
    protected static $callbacks = array();

    public static function register($callback)
    {
        if (!in_array($callback, self::$callbacks)) {
            self::$callbacks[] = $callback;
        }
    }

    public static function handle($exception)
    {
        foreach (self::$callbacks as $callback) {
            call_user_func($callback, $exception);
        }
    }
}

set_exception_handler('Exception_Handler::handle');

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

Это хорошее решение для проектирования?

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

Недостатки - это использование обратных вызовов (и я нахожу PHPUnitне сообщает о покрытии обратных вызовов), и ???

NB - я, возможно, не использую лучшие методы, чтобы определить природу исключения - instanceof «чувствовал» о правильном, но если есть лучшеЯ бы хотел то, знаешь ...

1 Ответ

0 голосов
/ 30 марта 2011

Я никогда не видел такого рода использования исключений для обработки веб-запросов где-либо еще. Идея кажется хорошей, но имейте в виду, что вы можете определить обработку только один раз для каждого приложения. В некоторых случаях вы захотите обработать Exception_Server_MethodNotAllowed как Exception_HTTP_405 в одной части вашего приложения и как Exception_HTTP_400 в другой части вашего приложения. Вы можете поймать это исключение где-то между вашим обработчиком исключений и вашим реальным броском, а затем попытаться переопределить исключение, но все станет очень быстро.

В моих приложениях я сразу же исправляю ошибки. Как только происходит что-то неожиданное, я советую либо сделать 404, либо 500. Для всего, что между ними, будет 500 и журнал ошибок. Если ошибка вызывает беспокойство, я изменяю обработку там, где она возникает.

...