Правила     Закладки     Карма    Календарь    Журналы    Помощь    Поиск    PDA    Чат   
        СМС-ки
   
Пейджер выключен!
Страницы: (5) [1] 2 3 ... Последняя » ( Перейти к первому непрочитанному сообщению )  
Фильтр авторов:    показать 
  скрыть
  Ответ в темуСоздание новой темыСоздание опроса

> Работа с исключениями и trigger_error
twin  
 ۩  [x] Дата
Цитировать сообщение

Пользователя сейчас нет на форуме



Глухой нуб
******

Профиль
Группа: Администратор
Почтальон группы
Сообщений: 15781
Пользователь №: 6543
На форуме: 8 лет, 3 месяца, 18 дней
Карма: 299

Трезвый :
6 лет, 27 дней


Бытует мнение, мол trigger_error() - это отстой. А exception рулит. Но всегда ли так?

Давайте рассмотрим подробнее использование его внутри фреймворка.

Триггер не передает управление в try... catch, максимум можно активировать собственный обработчик ошибок. На этом и базируется ошибка приверженцев, мол а что дальше делать? Пока оставим это. Вернемся к триггеру.

Он не выходит из скрипта. И это плюс на самом деле, а не минус. Потому что можно спокойно вернуть из метода false, и строить логику на ней (буду показывать на функциях для экономии места:
function example($value)
{
if (!is_string($value)) {
trigger_error('Ожидается строка');
return false;
}

return trim();
}

$var = example(1);

if (false === $var) {
echo '<br>Реагируем';
}


В итоге мы получим переход в блок реагирования. Отметим первое отличие от исключений. Потом обобщу. Исключения передают управление в блок catch, который может находиться черти где далеко от вызова функции. Это похоже на GOTO, который всеми порицается. А оборачивать в блок каждый вызов - ни чем не отличается от if... else, плюс сводит на нет возможности иерархий. Так что тут они на равных.

Однако при таком раскладе с trigger_error, интерпретатор вывалит на экран сообщение. Его конечно можно заглушить, но есть способ гораздо лучше. Написать кастомный обработчик. Не буду дублировать код, кто будет проверять, дополняйте листинг сверху.

set_error_handler('errorHandler');

function errorHandler($code, $message, $file, $line)
{
echo $message .' in '. $file .' on line '. $line;
}


Уже лучше, мы можем не только расскрасить и сделать дебаггер, но и выключить оповещение совсем. При этом ошибки с trigger_error автоматически логируются. А ексепшены нет. Вернее они тоже логируются, но только первый. Отметим второй плюс по сравнению с исключениями.

Однако тут мне возразят. Мол для эксепшенов тоже можно зарегистрировать свой обработчик, который сработает при всех неотловленных. И в нем сделать логирование. Да, это можно. Но тогда логироваться будут только неотловленные исключения. И не все будут этим заморачиваться. Значит тут у триггера приемущество.

Теперь дальше. Так как trigger_error не останавливат скрипт, то значит может показать и слогировать все ошибки, а не только первую. Ну показать нам не нужно, а вот слогировать - очень даже не помешало бы. Ексепшены такой возможности не дают.

Вроде пока по очкам триггер впереди. За что же он предается гонениям? Первое. В нем нет стека. Ну и что, сейчас исправим:
Вуаля:
set_error_handler('errorHandler');

function errorHandler($code, $message, $file, $line)
{
echo $message .' in '. $file .' on line '. $line;
var_dump(debug_backtrace());
}


Но это слишком просто. Есть проблема посложнее - привычки многих работать с try... catсh

А им это все не интересно. Ok. Не вопрос. А кто нам запретил кинуть эксепшен в обработчике? Причем можно сделать это опционально. Нравятся эксепшены, включим. Нет - нафиг надо. Добавляем второй обработчик:
if (true) {
set_error_handler('errorException');
} else {
set_error_handler('errorHandler');
}


function errorException($code, $message, $file, $line)
{
throw new Exception($message, $code);
}


Итак мы получили первую возможность настройки. Теперь все стогнатики могут наслаждаться ексепшенами. А кто не хочет, может не наслаждаться. Но при этом есть одна особенность. Все ошибки будут слогированы автоматически. Что невозможно при чистых исключениях.

Ага! скажут противники. А почему в локации указывается не тот файл и не та линия? Пердиманокль.

Ну ничего. Это тоже вполне решаемо. Делаем наследника от Exception и передаем их в него:
class TriggerException extends Exception
{
public function __construct($message, $code, $file, $line)
{
$this->file = $file;
$this->line = $line;
parent::__construct($message, $code);
}
}


function errorException($code, $message, $file, $line)
{
throw new TriggerException($message, $code, $file, $line);
}


Всё, получили то, что хотелось. Локация на месте.

Вроде бы победа очевидна. Но не тут то было. Аппологеты вводят в бой тяжелую артилерию. А где тут иерархия исключений? А? Как разделить ексепшены по типам? Тупик.

Однако нет безвыходных положений. Даже если тебя съели, всегда есть два выхода. :)

А вот возьмем и промаркеруем ошбки. Вот так:
defined('ABC_INVALID_ARGUMENT_EX') or define('ABC_INVALID_ARGUMENT_EX', '[004]');

function example($value)
{
if (!is_string($value)) {
trigger_error(ABC_INVALID_ARGUMENT_EX .'Ожидается строка');
return false;
}

return trim($value);
}


Теперь ничего не стоит в обработчике спарсить маркер, и на его основе построить иерархию:
function errorException($code, $message, $file, $line)
{
$type = substr($message, 0, 5);

switch ($type) {

case ABC_INVALID_ARGUMENT_EX :
$exception = 'InvalidArgumentException';
break;
// Тут все осталные
default :
throw new Exception($message, $code);
}

throw new $exception($message, $code, $file, $line);
}


Еще правда нужна библиотека наследников spl, но их всего 13 штук, не так уж и много.

Вот допустим один из них:
<?php

namespace ABC\Abc\Core\Exception;

/**
* Класс InvalidArgumentException
* Адаптирует trigger_error к Exception
* для корректного выброса исключения
* NOTE: Requires PHP version 5.5 or later
*
@author phpforum.su
*
@copyright © 2015
*
@license http://www.wtfpl.net/
*/

class InvalidArgumentException extends \InvalidArgumentException
{
/**
* Конструктор
*
*/

public function __construct($message, $code, $file, $line)
{
$this->file = $file;
$this->line = $line;
parent::__construct($message, $code);
}
}


Всё. Теперь можно юзать нативные SPL исключения, а можно свою иерархию создать. При этом получая все плюсы trigger_error() А вот наоборот уже вряд ли получится.

В моем фреймворке это уже работает. Вот они, голубчики.


Ну а теперь резюме. Хотя и так все очевидно. Я просто объединил их плюсы, нивелировав минусы.

1. Автоматическое логирование
Excepion no
trigger_error yes

2. Логирование всех ошибок
Excepion no
trigger_error yes

3. Возможность отфильтровать Notice
Excepion no
trigger_error yes

4. Переключение режимов с одного на другой
Excepion no
trigger_error yes

5. Возможность работы с прямой логикой, без передачи управления
Excepion no
trigger_error yes

Всё остальное они умеют делать одинаково.

Так что внутри фреймворка исключения будем бросать в самых крайних случаях. Когда без них совсем никак. Будем пользоваться маркированными trigger_error().

На дессерт фото моего дебаггера, чтобы развеять сомнения. И стек на месте, и локации, и листинг, и все что хочешь. А можно выключить и включить ексепшены.

При этом сами ексепшены точно так же работают в штатном режиме и ловятся дебаггером.[b]

Присоединённое изображение
Присоединённое изображение


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

Нужно уважать мнение оппонета. Ведь заблуждаться - его святое право.

Зачем ворошить старое, когда можно наворотить новое?

user posted image
PMСайт пользователяICQ
    0   Для быстрого поиска похожих сообщений выделите 1-2 слова в тексте и нажмите сюда Для быстрой цитаты из этого сообщения выделите текст и нажмите сюда
twin  
 ۩  Дата
Цитировать сообщение

Пользователя сейчас нет на форуме



Глухой нуб
******

Профиль
Группа: Администратор
Почтальон группы
Сообщений: 15781
Пользователь №: 6543
На форуме: 8 лет, 3 месяца, 18 дней
Карма: 299

Трезвый :
6 лет, 27 дней


Еще забыл один плюсик. При такой схеме попутно дебажатся нативные нотисы и варнинги тем же дебаггером. smile.gif


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

Нужно уважать мнение оппонета. Ведь заблуждаться - его святое право.

Зачем ворошить старое, когда можно наворотить новое?

user posted image
PMСайт пользователяICQ
    0   Для быстрого поиска похожих сообщений выделите 1-2 слова в тексте и нажмите сюда Для быстрой цитаты из этого сообщения выделите текст и нажмите сюда
Santehnick  
[x] Дата
Цитировать сообщение

Пользователя сейчас нет на форуме



Абориген
*****

Профиль
Группа: Форумчанин
Завсегдатай форума
Сообщений: 240
Пользователь №: 26735
На форуме: 5 лет, 10 месяцев, 13 дней
Карма: 15





//плохой код
function example($value)
{
if (!is_string($value)) {
trigger_error('Ожидается строка');
return false;
}

return trim();
}

$var = example(1);

if (false === $var) {
echo '<br>Реагируем';
}

//хороший код
function example($value)
{
if (!is_string($value)) {
throw new InvalidParam('Ожидается строка');
}
return trim();
}

try {
$var = example(1);
} catch (InvalidParam $e) {
echo '<br>Реагируем';
}


Цитата
Исключения передают управление в блок catch, который может находиться черти где далеко от вызова функции


try {
$var = example(1); //вызов функции
} catch (InvalidParam $e) { //catch блок который невероятно далеко от вызова функции
echo '<br>Реагируем';
}


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

Только вот код плохой. Тот же самый результат, можно сделать с помощью экзепшенов гораздо меньшими усилиями. Кода будет меньше, он будет чище, понятнее, легче в сопровождении. Вот что важно.
PM
    0   Для быстрого поиска похожих сообщений выделите 1-2 слова в тексте и нажмите сюда Для быстрой цитаты из этого сообщения выделите текст и нажмите сюда
twin  
 ۩  [x] Дата
Цитировать сообщение

Пользователя сейчас нет на форуме



Глухой нуб
******

Профиль
Группа: Администратор
Почтальон группы
Сообщений: 15781
Пользователь №: 6543
На форуме: 8 лет, 3 месяца, 18 дней
Карма: 299

Трезвый :
6 лет, 27 дней


Непробиваемый. Вот же заскорузло в мозгах. Ладно. А так:
//хороший код
function example($value)
{
if (!is_string($value)) {
trigger_error('Ожидается строка');
return false;
}

return trim();
}

$var = example(1);

if (false === $var) {
echo '<br>Реагируем';
}

// do something

// do something

// do something




// Плохой код

function example($value)
{
if (!is_string($value)) {
throw new InvalidParam('Ожидается строка');
}
return trim();
}

try {
$var = example(1);

// do something




// do something





// do something





// do something





// do something





// do something





// do something





} catch (InvalidParam $e) {
echo '<br>Реагируем';
}
Цитата (Santehnick @ 29.10.2015 - 17:43)
Тот же самый результат, можно сделать с помощью экзепшенов гораздо меньшими усилиями. Кода будет меньше, он будет чище, понятнее, легче в сопровождении. Вот что важно.

Пустые слова. Покажи. Как сделать с исключениями автоматическое логирование - раз, логирование всех ошибок скрипта, а не только первой - два, фильтрацию нотисов - три. (их вообще в ексепшенах сделать невозможно).

Если покажещь, и это будет чище и понятнее, я сниму перед тобой шляпу. Если нет, ну нет так нет. Мне и так всё ясно. Сложно отступать от годами нажитых стереотипов. :)


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

Нужно уважать мнение оппонета. Ведь заблуждаться - его святое право.

Зачем ворошить старое, когда можно наворотить новое?

user posted image
PMСайт пользователяICQ
    0   Для быстрого поиска похожих сообщений выделите 1-2 слова в тексте и нажмите сюда Для быстрой цитаты из этого сообщения выделите текст и нажмите сюда
Santehnick  
Дата
Цитировать сообщение

Пользователя сейчас нет на форуме



Абориген
*****

Профиль
Группа: Форумчанин
Завсегдатай форума
Сообщений: 240
Пользователь №: 26735
На форуме: 5 лет, 10 месяцев, 13 дней
Карма: 15




Цитата
Но тогда логироваться будут только неотловленные исключения.

А для чего логгировать пойманые исключения? Объясни. Бред какой-то.
PM
    0   Для быстрого поиска похожих сообщений выделите 1-2 слова в тексте и нажмите сюда Для быстрой цитаты из этого сообщения выделите текст и нажмите сюда
Santehnick  
Дата
Цитировать сообщение

Пользователя сейчас нет на форуме



Абориген
*****

Профиль
Группа: Форумчанин
Завсегдатай форума
Сообщений: 240
Пользователь №: 26735
На форуме: 5 лет, 10 месяцев, 13 дней
Карма: 15




Цитата
Если покажещь, и это будет чище и понятнее, я сниму перед тобой шляпу.

Запросто. Открой любой фреймворк и посмотри. Вообще любой. Ну кроме своего.
PM
    0   Для быстрого поиска похожих сообщений выделите 1-2 слова в тексте и нажмите сюда Для быстрой цитаты из этого сообщения выделите текст и нажмите сюда
twin  
 ۩  Дата
Цитировать сообщение

Пользователя сейчас нет на форуме



Глухой нуб
******

Профиль
Группа: Администратор
Почтальон группы
Сообщений: 15781
Пользователь №: 6543
На форуме: 8 лет, 3 месяца, 18 дней
Карма: 299

Трезвый :
6 лет, 27 дней


Нет. Ты покажи конкретно. Я показал. Вот напиши примерчик. Небольшой.

И еще.
try {
$var = example(1); //вызов функции
} catch (InvalidParam $e) { //catch блок который невероятно далеко от вызова функции
echo '<br>Реагируем';
}
Ты на каждую функцию пишешь catch? А как же с дублированием кода?

Я вот легко могу повторить все что ты сделал, просто включив режим exception. Ты сможешь повторить то, что я попросил?


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

Нужно уважать мнение оппонета. Ведь заблуждаться - его святое право.

Зачем ворошить старое, когда можно наворотить новое?

user posted image
PMСайт пользователяICQ
    0   Для быстрого поиска похожих сообщений выделите 1-2 слова в тексте и нажмите сюда Для быстрой цитаты из этого сообщения выделите текст и нажмите сюда
Santehnick  
Дата
Цитировать сообщение

Пользователя сейчас нет на форуме



Абориген
*****

Профиль
Группа: Форумчанин
Завсегдатай форума
Сообщений: 240
Пользователь №: 26735
На форуме: 5 лет, 10 месяцев, 13 дней
Карма: 15




Цитата

try {
  $var = example(1);

// do something




// do something





// do something





// do something





// do something





// do something





// do something




} catch (InvalidParam $e) {
  echo '<br>Реагируем';
}

Зачем тебе делать //do something в try блоке? //do something код не относится к исключению, которое мы обрабатываем. Так что


try {
$var = example(1);
} catch (InvalidParam $e) {
echo '<br>Реагируем';
}
// do something




// do something





// do something





// do something





// do something





// do something





// do something

PM
    0   Для быстрого поиска похожих сообщений выделите 1-2 слова в тексте и нажмите сюда Для быстрой цитаты из этого сообщения выделите текст и нажмите сюда
twin  
 ۩  Дата
Цитировать сообщение

Пользователя сейчас нет на форуме



Глухой нуб
******

Профиль
Группа: Администратор
Почтальон группы
Сообщений: 15781
Пользователь №: 6543
На форуме: 8 лет, 3 месяца, 18 дней
Карма: 299

Трезвый :
6 лет, 27 дней


Цитата (Santehnick @ 29.10.2015 - 17:55)
А для чего логгировать пойманые исключения? Объясни. Бред какой-то.

Я объяснял в прошлой ветке, но повторю еще раз.

Исключения вообще не предназначены для отлова логических ошибок. Они нужны для исключительных ситуаций. На которые действительно нужно реагировать какими то изменениями логики. Ты же предлагаешь бросать их на ошибки. Потому что trigger_error считаешь моветоном.

Ну а раз это ошибка, то её обязательно нужно логировать. Это репутация фреймворка - раз, большое подспорье в обслуживании два. Задаст кто-нибудь вопрос. А почему вот тут не работает. Я скажу - покажи лог. Что скажешь ты?



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

Нужно уважать мнение оппонета. Ведь заблуждаться - его святое право.

Зачем ворошить старое, когда можно наворотить новое?

user posted image
PMСайт пользователяICQ
    0   Для быстрого поиска похожих сообщений выделите 1-2 слова в тексте и нажмите сюда Для быстрой цитаты из этого сообщения выделите текст и нажмите сюда
twin  
 ۩  Дата
Цитировать сообщение

Пользователя сейчас нет на форуме



Глухой нуб
******

Профиль
Группа: Администратор
Почтальон группы
Сообщений: 15781
Пользователь №: 6543
На форуме: 8 лет, 3 месяца, 18 дней
Карма: 299

Трезвый :
6 лет, 27 дней


Цитата (Santehnick @ 29.10.2015 - 18:03)
Зачем тебе делать //do something в try блоке? //do something код не относится к исключению, которое мы обрабатываем. Так что

Тоесть ты все-таки пишешь catch на каждый вызов. Ну и нафига спрашивается? А если нужно одинаково обработать все ексепшены? Слогировать к примеру? Начинается повторение кода, раздувание листинга, пожирание памяти.

Еще раз повторю. Я могу сделать как ты. Ты сможешь, как я?


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

Нужно уважать мнение оппонета. Ведь заблуждаться - его святое право.

Зачем ворошить старое, когда можно наворотить новое?

user posted image
PMСайт пользователяICQ
    0   Для быстрого поиска похожих сообщений выделите 1-2 слова в тексте и нажмите сюда Для быстрой цитаты из этого сообщения выделите текст и нажмите сюда
twin  
 ۩  Дата
Цитировать сообщение

Пользователя сейчас нет на форуме



Глухой нуб
******

Профиль
Группа: Администратор
Почтальон группы
Сообщений: 15781
Пользователь №: 6543
На форуме: 8 лет, 3 месяца, 18 дней
Карма: 299

Трезвый :
6 лет, 27 дней


И опять. А если это плавающий баг, как без логов прожить? Радоваться красивой 500 на продакшене и спать спокойно?


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

Нужно уважать мнение оппонета. Ведь заблуждаться - его святое право.

Зачем ворошить старое, когда можно наворотить новое?

user posted image
PMСайт пользователяICQ
    0   Для быстрого поиска похожих сообщений выделите 1-2 слова в тексте и нажмите сюда Для быстрой цитаты из этого сообщения выделите текст и нажмите сюда
Arh  
Дата
Цитировать сообщение

Пользователя сейчас нет на форуме



146%
******

Профиль
Группа: Форумчанин
Завсегдатай форума
Сообщений: 2154
Пользователь №: 27172
На форуме: 5 лет, 9 месяцев, 19 дней
Карма: 73




А зачем вообще наследовать стандартный класс Exception ?
Почему нельзя вызывать обычный?


--------------------
:)
PMСайт пользователя
    0   Для быстрого поиска похожих сообщений выделите 1-2 слова в тексте и нажмите сюда Для быстрой цитаты из этого сообщения выделите текст и нажмите сюда
twin  
 ۩  Дата
Цитировать сообщение

Пользователя сейчас нет на форуме



Глухой нуб
******

Профиль
Группа: Администратор
Почтальон группы
Сообщений: 15781
Пользователь №: 6543
На форуме: 8 лет, 3 месяца, 18 дней
Карма: 299

Трезвый :
6 лет, 27 дней


А ты вообще читал, что там у меня написано? Я кажется все по полкам разложил.


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

Нужно уважать мнение оппонета. Ведь заблуждаться - его святое право.

Зачем ворошить старое, когда можно наворотить новое?

user posted image
PMСайт пользователяICQ
    0   Для быстрого поиска похожих сообщений выделите 1-2 слова в тексте и нажмите сюда Для быстрой цитаты из этого сообщения выделите текст и нажмите сюда
Arh  
Дата
Цитировать сообщение

Пользователя сейчас нет на форуме



146%
******

Профиль
Группа: Форумчанин
Завсегдатай форума
Сообщений: 2154
Пользователь №: 27172
На форуме: 5 лет, 9 месяцев, 19 дней
Карма: 73




Чё то читал, но там много букв =) Вкратце не получится?


--------------------
:)
PMСайт пользователя
    0   Для быстрого поиска похожих сообщений выделите 1-2 слова в тексте и нажмите сюда Для быстрой цитаты из этого сообщения выделите текст и нажмите сюда
Arh  
Дата
Цитировать сообщение

Пользователя сейчас нет на форуме



146%
******

Профиль
Группа: Форумчанин
Завсегдатай форума
Сообщений: 2154
Пользователь №: 27172
На форуме: 5 лет, 9 месяцев, 19 дней
Карма: 73




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


--------------------
:)
PMСайт пользователя
    0   Для быстрого поиска похожих сообщений выделите 1-2 слова в тексте и нажмите сюда Для быстрой цитаты из этого сообщения выделите текст и нажмите сюда
  Быстрый ответ
Информация о Госте
Введите Ваше имя
Кнопки кодов
Для вставки цитаты, выделите нужный текст и
НАЖМИТЕ СЮДА
Введите сообщение
Смайлики
:huh:  :o  ;) 
:P  :D  :lol: 
B)  :rolleyes:  <_< 
:)  :angry:  :( 
:unsure:  :blink:  :ph34r: 
     
Показать всё

Опции сообщения  Включить смайлики?
 Включить подпись?
 
1 Пользователей читают эту тему (1 Гостей и 0 Скрытых Пользователей)
0 Пользователей:

Опции темыСтраницы: (5) [1] 2 3 ... Последняя » Ответ в темуСоздание новой темыСоздание опроса