За последние 24 часа нас посетили 18092 программиста и 1675 роботов. Сейчас ищет 1001 программист ...

Класс для обработки ошибок Error (error handler)

Тема в разделе "Решения, алгоритмы", создана пользователем Padaboo, 7 ноя 2010.

  1. Padaboo

    Padaboo Старожил
    Команда форума Модератор

    С нами с:
    26 окт 2009
    Сообщения:
    5.242
    Симпатии:
    1
    Еше один мой ночной бред, но вроде бы на этот раз внятный.
    Что може: дебаг мод (по моему удался), логирование, отправка на почту (это не проверял).
    Говорит что за ошибка, в каком файле, на какой линии, выводит пронумерованный код с подсветкой и
    print_r всего что можно.
    Просто скопируйте себе весь код и не забудьте создать файл с логом
    error.log в той же папке, если понравится смотрите __construct
    PHP:
    1. <?php
    2. /**
    3.  * Description of Error
    4.  * Класс для обработки ошибок
    5.  * @author padaboo
    6.  */
    7. class Error {
    8.     /**
    9.      * Типы ошибок
    10.      * @var array $errortype
    11.      */
    12.     private $errortype = array (
    13.                 1            => 'Ошибка',
    14.                 2            => 'Опасность',
    15.                 4            => 'Синтаксическая ошибка',
    16.                 8            => 'Предупреждение',
    17.                 16           => 'Ошибка ядра',
    18.                 32           => 'Опасность ядра',
    19.                 64           => 'Ошибка компилирования',
    20.                 128          => 'Опасность компилирования',
    21.                 256          => 'Ошибка пользователя',
    22.                 512          => 'Опасность пользователя',
    23.                 1024         => 'Предупреждение пользователя',
    24.                 2048         => 'Предупреждение времени выполнения',
    25.                 4096         => 'Фатальная ошибка '
    26.                 );
    27.     /**
    28.      * включен или выключен дебаг
    29.      * 1 или 0
    30.      * @var int $debug
    31.      */
    32.     private $debug;
    33.     /**
    34.      * включено или выключено логирование
    35.      * 1 или 0
    36.      * @var int $log
    37.      */
    38.     private $log;
    39.     /**
    40.      * Сообщение которое получит пользователь
    41.      * в случае ошибки
    42.      * @var string $userMessage
    43.      */
    44.     private $userMessage;
    45.     /**
    46.      * Сообщеник которое получит
    47.      * разработчик при включенном
    48.      * дебаге в ini файле
    49.      * @var string $debugMessage
    50.      */
    51.     private $debugMessage;
    52.     /**
    53.      * Сообщение которое пойдет
    54.      * в лог файл
    55.      * @var string $logMessage
    56.      */
    57.     private $logMessage;
    58.     /**
    59.      * Путь до файла с логами
    60.      * @var string $logFile
    61.      */
    62.     private $logFile = '';
    63.     /**
    64.      * нужно ли отправлять почту
    65.      * с ошибкой админу (0/1)
    66.      * @var string $mail
    67.      */
    68.     private $mail;
    69.      /**
    70.      * почта
    71.      * @var string $adminMail
    72.      */
    73.     private $adminMail;
    74.     /**
    75.      * Путь до файла с логом
    76.      * @param string $file
    77.      * нужно ли записывать в лог ошибка
    78.      * @param int $log (1/0)
    79.      * дебаг
    80.      * @param int $debug (1/0)
    81.      * нужно ли отправлять ошибку на почту
    82.      * @param int $mail (1/0)
    83.      * почта
    84.      * @param string $adminMail
    85.      */
    86.     public function  __construct($file, $log, $debug, $mail = 0, $adminMail = ''){
    87.         if(!file_exists($file)){
    88.             die("Не найден файл $file для логов");
    89.         }
    90.         $this->logFile    = $file;
    91.         $this->log        = $log;
    92.         $this->debug      = $debug;
    93.         $this->mail       = $mail;
    94.         $this->adminMail  = $adminMail;
    95.     }
    96.     /**
    97.      * Функиция для обработки ошибок
    98.      */
    99.     public function handler($errno, $errstr, $errfile, $errline){
    100.         $this->userMessage  = "Произошла ошибка, отряд специальо обученных макак
    101.                               уже отправлен на устранение неполадок";
    102.         $this->debugMessage = $this->getDebugMessage($errno, $errstr, $errfile, $errline);
    103.         $this->logMessage   = '['.date('d.m.Y H:i:s', time()).']' . "[".$this->errortype[$errno].
    104.                               "] $errstr in file $errfile on in line $errline \r\n";
    105.         $this->display();
    106.     }
    107.     /**
    108.      * Выводит отладочную информацию.
    109.      */
    110.     private function display(){
    111.         echo ($this->debug)? $this->debugMessage : $this->userMessage;
    112.         if ($this->log)
    113.             error_log($this->logMessage, 3, $this->logFile);
    114.  
    115.         if($this->mail){
    116.             //спасибо Apple :);
    117.             if(!filter_var($this->adminMail, FILTER_VALIDATE_EMAIL))
    118.                 die("Нeправильный e-mail");
    119.    
    120.             $this->logMessage .= " \r\n На вашем сайте " . $_SERVER[HTTP_HOST].$_SERVER[PHP_SELF] ;
    121.             mail($this->adminMail, 'Сообщение об ошибке', $this->logMessage);
    122.         }
    123.     }
    124.     /**
    125.     * Формирует сообщение дебага
    126.     */
    127.     private function getDebugMessage($errno, $errstr, $errfile, $errline ){
    128.         $message  = $this->errortype[$errno]." : $errstr в файле $errfile на линии $errline <hr>";
    129.         $message .= $this->highlight_num($errfile);
    130.         $message .= '<hr><small>Массив $_REQUEST:</small><br/>';
    131.         $message .= '<pre>' . print_r($_REQUEST, true) .'</pre><hr>';
    132.         $message .= '<small>Массив $_COOKIE:</small><br/>';
    133.         $message .= '<pre>' . print_r($_COOKIE, true) .'</pre><hr>';
    134.         $message .= '<small>Массив $_SESSION:</small><br/>';
    135.         $message .= isset($_SESSION)? '<pre>' . print_r($_SESSION, true) .'</pre><hr>' : 'Не задан<hr>';
    136.         $message .= '<small>Массив $_FILES:</small><br/>';
    137.         $message .= '<pre>' . print_r($_FILES, true) .'</pre><hr>';
    138.         $message .= '<small>Массив $_SERVER:</small><br/>';
    139.         $message .= '<pre>' . print_r($_SERVER, true) .'</pre><hr>';
    140.         return $message;
    141.     }
    142.     /**
    143.     * нумерует строчки php
    144.     * спизжено с мануала
    145.     * @param string $file
    146.     */
    147.     private function highlight_num($file) {
    148.         $lines = implode(range(1, count(file($file))), '<br />');
    149.         $content  = highlight_file($file, true);
    150.         $content .=' <style type="text/css">
    151.                 .num {
    152.                 float: left;
    153.                 color: gray;
    154.                 font-size: 11px;    
    155.                 font-family: monospace;
    156.                 text-align: right;
    157.                 margin-right: 3pt;
    158.                 padding-right: 3pt;
    159.                 border-right: 1px solid gray;}
    160.  
    161.                 body {margin: 0px; margin-left: 3px;}
    162.                 td {vertical-align: top;}
    163.                 code {white-space: nowrap;}
    164.                 span { font-size: 11px; }
    165.                 </style>';
    166.         return "<table><tr><td class=\"num\">\n$lines\n</td><td>\n$content\n</td></tr></table>";
    167.     }  
    168. }
    169.  
    170.         $errorClass   = new Error('error.log', 1, 1);
    171.         $errorMethod  = 'handler';
    172.         set_error_handler(array($errorClass, $errorMethod));
    173.         //trigger_error('Произошла какая то хуйня !', E_USER_ERROR);
    174.         1/0
    175.        
    176. ?>
     
  2. Апельсин

    Апельсин Активный пользователь

    С нами с:
    20 мар 2010
    Сообщения:
    3.645
    Симпатии:
    2
    Неугомонный :)
     
  3. Padaboo

    Padaboo Старожил
    Команда форума Модератор

    С нами с:
    26 окт 2009
    Сообщения:
    5.242
    Симпатии:
    1
    Апельсин
    еше около 12 классов (основных, а еше патерны, интерфейсы и т.п.) будет, если сил и времени хватит
    и получится 1001 фрейм ворк общего назначения
    а потом поверх буду строить CMS, еше сверху соц сеть (ты ж сам сказал что кто без соц сети тот лох :D) шутко, в пень соц сеть
     
  4. Апельсин

    Апельсин Активный пользователь

    С нами с:
    20 мар 2010
    Сообщения:
    3.645
    Симпатии:
    2
    Padaboo
    я в коде ошибку нашел.

    PHP:
    1. <?php
    2. //trigger_error('Произошла какая то фиг !', E_USER_ERROR);
    там не хватает "ня" у слова "фиг"
    :D )))))))
     
  5. Padaboo

    Padaboo Старожил
    Команда форума Модератор

    С нами с:
    26 окт 2009
    Сообщения:
    5.242
    Симпатии:
    1
    Апельсин
    а это в админке стоит слова х у й* на фиг заменять
     
  6. [vs]

    [vs] Суперстар
    Команда форума Модератор

    С нами с:
    27 сен 2007
    Сообщения:
    10.559
    Симпатии:
    632
    говнокод, логгер убивает скрипт ничего даже не написав в лог)))
     
  7. Padaboo

    Padaboo Старожил
    Команда форума Модератор

    С нами с:
    26 окт 2009
    Сообщения:
    5.242
    Симпатии:
    1
    [vs]
    а куда ты собрался писать лог, если файл лога не существует, и вообще зачем это во время настройки самого логера
     
  8. Костян

    Костян Активный пользователь

    С нами с:
    12 ноя 2009
    Сообщения:
    1.724
    Симпатии:
    1
    Адрес:
    адуктО
    а если файл лога существует а писать в него нельзя?
     
  9. Ensiferum

    Ensiferum Активный пользователь

    С нами с:
    11 июл 2010
    Сообщения:
    1.292
    Симпатии:
    0
    Адрес:
    из секты поклонников Нео
    Padaboo
    Есть чё?
     
  10. Padaboo

    Padaboo Старожил
    Команда форума Модератор

    С нами с:
    26 окт 2009
    Сообщения:
    5.242
    Симпатии:
    1
    Костян
    тогда
    Warning: error_log(error.log) [function.error-log]: failed to open stream
    хотя трудно такую ситуацию представить, сначала нормально настраиваешь, а потом функция логирования сама вроде как пакует старый файл и создает новый...
     
  11. [vs]

    [vs] Суперстар
    Команда форума Модератор

    С нами с:
    27 сен 2007
    Сообщения:
    10.559
    Симпатии:
    632
    Это в идеале. Лучше чтобы класс имел какой-нибудь дефолтный лог-файл (trashcan.log) и если пользовательский файл задан неверно - писал ошибки в него (в т.ч. и ошибку что пользовательский файл задан неверно).
     
  12. pohapecoder

    pohapecoder Активный пользователь

    С нами с:
    16 окт 2010
    Сообщения:
    63
    Симпатии:
    0
    Уже есть: http://dklab.ru/lib/Debug_ErrorHook/

    А вот мой велосипед для вывода ошибок в firebug для файрфокса (естественно работает только для html-контента),
    подключаем в начале основного файла приложения и наслаждаемся:
    PHP:
    1.  
    2. <?php
    3.  
    4. if (strpos($_SERVER["HTTP_HOST"], "localhost") !== false) {
    5.  
    6.     function my_debug_trace($s, $vars=array(), $type="log") {
    7.         if (!in_array($type, array("info", "warn", "error", "log", "debug")))
    8.             return;
    9.         print "<script>console.$type(" .
    10.                 json_encode((sizeof($vars) > 0 ?
    11.                     ($s . ($type != "log" ? "Local: " : " ") . "%o") : $s)) .
    12.                 (sizeof($vars) > 0 ? "," . json_encode($vars) : "") .
    13.             ");</script>\n";
    14.     }
    15.  
    16.     function my_debug_error_handler($errno, $errstr, $errfile, $errline, $vars) {
    17.         $found_error = false;
    18.         $errors = array(
    19.                 E_USER_ERROR => "error",
    20.                 E_ERROR => "error",
    21.                 E_USER_WARNING => "warn",
    22.                 E_WARNING => "warn",
    23.                 E_USER_NOTICE => "info",
    24.                 E_NOTICE => "info",
    25.                 E_STRICT => "info");
    26.  
    27.         foreach ($errors as $e => $v)
    28.             if ($errno == $e) {
    29.                 if (error_reporting() & $e)
    30.                     my_debug_trace("[$errno] $errfile:$errline\n$errstr\n", $vars, $v);
    31.                 $found_error = true;
    32.                 break;
    33.             }
    34.            
    35.         if (!$found_error)
    36.             my_debug_trace("[$errno] Unknown error - $errfile:$errline\n$errstr\n", $vars, "error");
    37.        
    38.         return false;
    39.     }
    40.  
    41.     set_error_handler("my_debug_error_handler");
    42.  
    43.     function my_debug_exception_handler($e) {
    44.         my_debug_trace("[" . $e->getCode() . "] " . $e->getFile() . ":" . $e->getLine() . "\n" .
    45.             $e->getMessage() . "\n",
    46.             $e->getTrace(), "error");
    47.     }
    48.  
    49.     set_exception_handler("my_debug_exception_handler");
    50.  
    51.     function my_debug_last_error() {
    52.         $e = error_get_last();
    53.         if (($e["type"] & E_COMPILE_ERROR) ||
    54.                 ($e["type"] & E_ERROR) ||
    55.                 ($e["type"] & E_CORE_ERROR) ||
    56.                 ($e["type"] & E_RECOVERABLE_ERROR))
    57.         my_debug_trace("[" . $e["type"] . "] " . $e["file"] . ":" . $e["line"] . "\n" .
    58.             $e["message"] . "\n", array(), "error");
    59.     }
    60.  
    61.     register_shutdown_function("my_debug_last_error");
    62. }
    63.  
     
  13. Padaboo

    Padaboo Старожил
    Команда форума Модератор

    С нами с:
    26 окт 2009
    Сообщения:
    5.242
    Симпатии:
    1
    [vs]
    не плохая идея, наверное таки сделаю, спасибо
    pohapecoder
    какой то он не понятный
     
  14. Костян

    Костян Активный пользователь

    С нами с:
    12 ноя 2009
    Сообщения:
    1.724
    Симпатии:
    1
    Адрес:
    адуктО
    Padaboo
    а еще круче, когда Internal Server Error - тебе приходит СМС-ка ;)
     
  15. Padaboo

    Padaboo Старожил
    Команда форума Модератор

    С нами с:
    26 окт 2009
    Сообщения:
    5.242
    Симпатии:
    1
    Костян
    не плохо было бы, а что вполне реально такое сделать по моему))
     
  16. Костян

    Костян Активный пользователь

    С нами с:
    12 ноя 2009
    Сообщения:
    1.724
    Симпатии:
    1
    Адрес:
    адуктО
    конечно, особенно когда есть два сервера )))
    у меня например СМС-ки приходят, когда комментарий добавляется и еще там по определённым причинам, только чур ночью не комментировать...
     
  17. Koc

    Koc Активный пользователь

    С нами с:
    3 мар 2008
    Сообщения:
    2.253
    Симпатии:
    0
    Адрес:
    \Ukraine\Dnepropetrovsk
    а еще есть Zend_Log который на-раз можно прикрутить как error/uncauth exc handler
     
  18. [vs]

    [vs] Суперстар
    Команда форума Модератор

    С нами с:
    27 сен 2007
    Сообщения:
    10.559
    Симпатии:
    632
    А я даже не стал писать error_handler, потому что меня вполне устраивает лог php.
    Просто написал класс для записи произвольных ошибок
    PHP:
    1. <?php
    2. // Ведение лога
    3. class Spirit_Log
    4. {
    5.     private static $logtext = array();
    6.  
    7.     private static function assing($params) {
    8.         if (Spirit_Registry::getInstance()->config()->DisplayLog() == 1) {
    9.             echo "\r\n<pre>";
    10.             print_r($params);
    11.             echo "\r\n</pre>";
    12.         }
    13.         $time = date('H:i:s');
    14.         $case = 1;
    15.         while (key_exists($time.'('.$case.')', self::$logtext)) {
    16.             $case++;
    17.         }
    18.         self::$logtext[$time.'('.$case.')'] = $params;
    19.     }
    20.  
    21.     public static function notice($text) {
    22.         self::assing(array('Level'=>'Notice', 'Text'=>$text));
    23.     }
    24.  
    25.     public static function warning($text) {
    26.         self::assing(array('Level'=>'Warning', 'Text'=>$text));
    27.     }
    28.  
    29.     public static function exception($e) {
    30.         self::assing(array('Level'=>'Exception',
    31.             'Text'=>'Message: '.$e->getMessage().
    32.                 'File: '.$e->getFile().', Line: '.$e->getLine()
    33.         ));
    34.     }
    35.  
    36.     public static function save() {
    37.         if (empty(self::$logtext) ||
    38.                 Spirit_Registry::getInstance()->config()->WriteLog() == 0) {
    39.             return false;
    40.         }
    41.         $text = "\r\nBegin:\r\n";
    42.         foreach (self::$logtext as $time=>$record) {
    43.             $text .= ' '.$time.'::'.$record['Level'].'::'.$record['Text']."\r\n";
    44.         }
    45.         $text .= "Eof;\r\n";
    46.         $filename = SPIRIT_PATH.'/Logs/'.date('m_d_Y').'.log';
    47.         if (file_exists($filename)) {
    48.             $fp = fopen($filename, 'a');
    49.             fwrite($fp, $text);
    50.         }
    51.         else {
    52.             file_put_contents($filename, $text);
    53.         }
    54.         self::$logtext = array();
    55.     }
    56. }
    в шатдаун-функции вызывается метод save.
    Интересная особенность - т.к. в одну секунду может быть выполнено несколько разных скриптов, словами Begin и Eof и отступами разграничиваются сеансы.
     
  19. Костян

    Костян Активный пользователь

    С нами с:
    12 ноя 2009
    Сообщения:
    1.724
    Симпатии:
    1
    Адрес:
    адуктО
    DisplayLog() == 1
     
  20. tommyangelo

    tommyangelo Старожил

    С нами с:
    6 дек 2009
    Сообщения:
    2.549
    Симпатии:
    0
    Адрес:
    Мариуполь
    Костян
    А как ты с смс работаешь, если не секрет ))
    Знаю раньше можно было почту отправить типа 123456789@operator.ru ))
     
  21. Костян

    Костян Активный пользователь

    С нами с:
    12 ноя 2009
    Сообщения:
    1.724
    Симпатии:
    1
    Адрес:
    адуктО
    ну так и делаю, мой оператор позволяет
     
  22. [vs]

    [vs] Суперстар
    Команда форума Модератор

    С нами с:
    27 сен 2007
    Сообщения:
    10.559
    Симпатии:
    632
    не понял тебя
     
  23. Padaboo

    Padaboo Старожил
    Команда форума Модератор

    С нами с:
    26 окт 2009
    Сообщения:
    5.242
    Симпатии:
    1
    [vs]
    PHP:
    1. <?php
    2. if(1){
    3.   echo ':)';
    4. }
     
  24. Koc

    Koc Активный пользователь

    С нами с:
    3 мар 2008
    Сообщения:
    2.253
    Симпатии:
    0
    Адрес:
    \Ukraine\Dnepropetrovsk
    оо, мсье не знает о наличии флага FILE_APPEND у file_put_contents?

    Код (Text):
    1. config()->DisplayLog()
    не могу понять, чем обусловлен выбор больших и маленьких букв для названия методов. Почему конфиг с маленькой а дисплей лог с большой называется?
     
  25. [vs]

    [vs] Суперстар
    Команда форума Модератор

    С нами с:
    27 сен 2007
    Сообщения:
    10.559
    Симпатии:
    632
    точняк, надо displayLog