Исключения путаницы - PullRequest
3 голосов
/ 22 мая 2010

Я пытаюсь создать сайт с использованием ООП в PHP. Все говорят о синглтоне, герметизации, MVC и использовании исключений. Поэтому я попытался сделать это так:

Класс здания весь сайт:

class Core
{
    public $is_core;
    public $theme;
    private $db;
    public $language;
    private $info;
    static private $instance;

    public function __construct($lang = 'eng', $theme = 'default')
    {
        if(!self::$instance)
        {
            try
            {
                $this->db = new sdb(DB_TYPE.':host='.DB_HOST.';dbname='.DB_NAME, DB_USER, DB_PASS);
            }
            catch(PDOException $e)
            {
                throw new CoreException($e->getMessage());
            }
            try
            {
                $this->language = new Language($lang);
            }
            catch(LangException $e)
            {
                throw new CoreException($e->getMessage());
            }
            try
            {
                $this->theme = new Theme($theme);
            }
            catch(ThemeException $e)
            {
                throw new CoreException($e->getMessage());
            }
        }
        return self::$instance;
    }
    public function getSite($what)
    {
        return $this->language->getLang();
    }
    private function __clone() { }

}

Класс управления темами

class Theme
{
    private $theme;
    public function __construct($name = 'default')
    {
        if(!is_dir("themes/$name"))
        {
            throw new ThemeException("Unable to load theme $name");
        }
        else
        {
            $this->theme = $name;
        }
    }
    public function getTheme()
    {
        return $this->theme;
    }
    public function display($part)
    {
        if(!is_file("themes/$this->theme/$part.php"))
        {
            throw new ThemeException("Unable to load theme part: themes/$this->theme/$part.php");
        }
        else
        {
            return 'So far so good';
        }
    }

}

И использование:

error_reporting(E_ALL);

require_once('config.php');
require_once('functions.php');

try
{
    $core = new Core();
}
catch(CoreException $e)
{
    echo 'Core Exception: '.$e->getMessage();
}
echo $core->theme->getTheme();
echo "<br />";
echo $core->language->getLang();

try
{
    $core->theme->display('footer');
}
catch(ThemeException $e)
{
    echo $e->getMessage();
}

Мне не нравятся эти обработчики исключений - я не хочу ловить их как некоторых покемонов ... Я хочу использовать простые вещи: $ Core-> theme-> дисплей ( 'сноска'); И если что-то не так, и режим отладки включен, то приложение показывает ошибку. Что мне делать?

Ответы [ 3 ]

1 голос
/ 22 мая 2010

Я не знаком с PHP, но вам определенно следует прекратить делать исключения для покемонов. Во-первых, не должно быть необходимости заменять каждое исключение (PDOException) конкретным исключением (CoreException). Во-вторых, используйте несколько блоков catch в вашем разделе использования, например:

try
{
   $core->theme->display('footer');
}
catch(ThemeException $e)
{
   echo $e->getMessage();
}
catch(PDOException $e)
{
   echo $e->getMessage();
}

Ваш класс "Ядро" может значительно уменьшиться (больше не нужно пытаться поймать каждый предмет). Конечно, вы будете показывать больше блоков уловов на более высоком уровне, но это то, что вы должны делать с ООП и исключениями.

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

1 голос
/ 07 июля 2010

Вы можете рассмотреть возможность использования собственного обработчика ошибок и настройки его для всего приложения. Это действительно правильный подход, только если вы работаете в шаблоне проектирования, таком как Front Controller, где обработчик может быть легко настроен для всего приложения.

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

<code><?php
class ErrorHandler
{
    // Private constructor to prevent direct creation of object
    private function __construct()
    {
    }

    /* Set user error-handler method to ErrorHandler::Handler method */
    public static function SetHandler($errTypes = ERROR_TYPES)
    {
        return set_error_handler(array ('ErrorHandler', 'Handler'), $errTypes);
    }

    // Error handler method
    public static function Handler($errNo, $errStr, $errFile, $errLine)
    {

        $backtrace = ErrorHandler::GetBacktrace(2);

        $error_message = "\nERRNO: $errNo\nTEXT: $errStr" .
                     "\nLOCATION: $errFile, line " .
                     "$errLine, at " . date('F j, Y, g:i a') .
                     "\nShowing backtrace:\n$backtrace\n\n";

        // Email the error details, in case SEND_ERROR_MAIL is true
        if (SEND_ERROR_MAIL == true)
        error_log($error_message, 1, ADMIN_ERROR_MAIL, "From: " .
        SENDMAIL_FROM . "\r\nTo: " . ADMIN_ERROR_MAIL);

        // Log the error, in case LOG_ERRORS is true
        if (LOG_ERRORS == true)
        error_log($error_message, 3, LOG_ERRORS_FILE);

        /* Warnings don't abort execution if IS_WARNING_FATAL is false
         E_NOTICE and E_USER_NOTICE errors don't abort execution */
        if (($errNo == E_WARNING && IS_WARNING_FATAL == false) ||
        ($errNo == E_NOTICE || $errNo == E_USER_NOTICE))
        // If the error is nonfatal ...
        {
            // Show message only if DEBUGGING is true
            if (DEBUGGING == true)
            echo '<div class="error_box"><pre>' . $error_message . '
'; } еще // Если ошибка фатальная ... { // Показать сообщение об ошибке если (ОТЛАДКА == верно) echo '
'. $error_message . '
'; еще эхо SITE_GENERIC_ERROR_MESSAGE; // Остановим обработку запроса выход(); } } // Создает сообщение трассировки публичная статическая функция GetBacktrace ($ irrelevantFirstEntries) { $ s = ''; $ MAXSTRLEN = 64; $ trace_array = debug_backtrace (); для ($ i = 0; $ i <$ irrelevantFirstEntries; $ i ++) array_shift ($ trace_array); $ tabs = sizeof ($ trace_array) - 1; foreach ($ trace_array как $ arr) { $ tabs - = 1; if (isset ($ arr ['class'])) $ s. = $ arr ['class']. ''; $ args = array (); if (! empty ($ arr ['args'])) foreach ($ arr ['args'] как $ v) { если (is_null ($ v)) $ args [] = 'null'; elseif (is_array ($ v)) $ args [] = 'Array ['. sizeof ($ v). ']'; elseif (is_object ($ v)) $ args [] = 'Object:'. get_class ($ v); elseif (is_bool ($ v)) $ args [] = $ v? 'true': 'false'; еще { $ v = (строка) @ $ v; $ str = htmlspecialchars (substr ($ v, 0, $ MAXSTRLEN)); if (strlen ($ v)> $ MAXSTRLEN) $ str. = '...'; $ args [] = '"'. $ str. '"'; } } $ s. = $ arr ['function']. '('. implode (',', $ args). ')'; $ line = (isset ($ arr ['line'])? $ arr ['line']: 'unknown'); $ file = (isset ($ arr ['file'])? $ arr ['file']: 'unknown'); $ s. = sprintf ('# line% 4d, файл:% s', $ line, $ file); $ s. = "\ n"; } вернуть $ s; } } ?>

Затем вы можете определить несколько простых констант для определения некоторых базовых поведений.

//determines if the application will fail on E_WARNING level errors.
define('IS_WARNING_FATAL', true);
//determines error message shown
define('DEBUGGING', true);
// The error types to be reported
define('ERROR_TYPES', E_ALL);

// Settings about mailing the error messages to admin
define('SEND_ERROR_MAIL', false);
define('ADMIN_ERROR_MAIL', 'Administrator@example.com');
define('SENDMAIL_FROM', 'Errors@example.com');


//Saves errors to a file when true
define('LOG_ERRORS', false);
define('LOG_ERRORS_FILE', 'path-to-error-log');
/* Generic error message to be displayed instead of debug info
 (when DEBUGGING is false) */
define('SITE_GENERIC_ERROR_MESSAGE', '<h1>An unknown error occurred!  Our webmaster has been notified.</h1>');
1 голос
/ 22 мая 2010

Если вы не хотите перехватывать и игнорировать их, то вы можете также не выбрасывать исключения (на самом деле, альтернативы нет - исключения должны быть перехвачены или выполнение скрипта закончится).

Сделайте что-то вроде

if (debug_is_on())
    throw new MyException(...);

В качестве альтернативы вы можете вместо этого выбросить ошибки , а затем настроить уровень error_reporting.

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