Форум: "Прочее";
Текущий архив: 2009.12.06;
Скачать: [xml.tar.bz2];
ВнизPHP: error_reporting() возвращает непредвиденно ноль Найти похожие ветки
← →
Piter © (2009-10-08 20:40) [0]Некий движок написанный на PHP, есть переопределение возврата ошибок:
set_error_handler(array($Error, "general"));
Метод general:
...
public function general($errno, $errmsg, $filename, $linenum, $vars)
{
$this->addStack($errno, $errmsg, $filename, $linenum);
$this->display();
}
private function addStack($errno, $errmsg, $filename, $linenum)
{
$this->stack[] = array($errno, $errmsg, $filename, $linenum);
}
public function display($error_reporting = NULL)
{
if (!isset($error_reporting))
{
$error_reporting = error_reporting(); // ВОТ ЗДЕСЬ ПРОВЕРКА error_reporting()
}
.............
Не удивляйтесь некоей нелогичности, это в тестовых целях.
Итак, функция error_reporting() как и положено возвращает E_ALL, то что стоит в опциях PHP.ini. До определенного момента (((
Используется PEAR, в частности подключается PEAR/DB.php, в проекте есть код:$DB = DB::connect("строка коннекта");
, DB - это класс из PEAR
До выполнения этой строки error_reporting() из метода display возвращал E_ALL в случае ошибки. Последнее полученное сообщение, когда error_reporting() еще возвращал E_ALL было:
>Runtime Notice: Non-static method DB::parseDSN() should not be called statically in file D:\Program Files\Apache\Apache\htdocs\includes\PEAR\DB.php on line 358
При получении следующего сообщения:
>Runtime Notice: Assigning the return value of new by reference is deprecated in file D:\Program Files\Apache\Apache\htdocs\includes\PEAR\DB\common.php on line 958
В функции display уже error_reporting() возвращает ноль. При этом, поиск по PEAR не дает наличие ни в одном модуле строки "error_reporting"...
Почему же значение может меняться?! Его можно поменять функцией, отличной от error_reporting(val)?!
← →
McSimm © (2009-10-08 20:54) [1]
>
> В функции display уже error_reporting() возвращает ноль.
>
как проверял ?
← →
McSimm © (2009-10-08 20:56) [2]Я к тому, что вероятно заход в обрабочик был по экранированной ошибке
@ statement
← →
McSimm © (2009-10-08 21:00) [3]Вот код, воспроизводит это:
set_error_handler("myErrorHandler");
error_reporting(E_ALL);
@$a = $b;
function myErrorHandler($errno, $errstr, $errfile, $errline)
{
$e = error_reporting();
var_dump($e);
}
← →
Piter © (2009-10-08 21:07) [4]McSimm © (08.10.09 20:54) [1]
как проверял ?
добавил строчку:echo error_reporting();
и увидел 0
McSimm © (08.10.09 21:00) [3]
Вот код, воспроизводит это
выдало: int(0)
Но я не понял про "по экранированной ошибке"... Как это?
← →
Piter © (2009-10-08 21:07) [5]McSimm © (08.10.09 20:56) [2]
@ statement
а, все, понял
← →
Piter © (2009-10-08 21:11) [6]но как-то бредово... Получается, экранирование ошибки приводит к тому, что обработчик все таки вызывается, но при этом error_reporting устанавливается в 0?!
Очень похоже на костыли какие-то... Уж лучше бы каким-нибудь аргуметом передавался флаг - надо ли экранировать ошибку...
А как-нибудь побороть можно? Например, узнать истинное значение error_reporting... Ну которое в PHP.ini по идее стоит.
← →
McSimm © (2009-10-08 21:15) [7]
> которое в PHP.ini
ini_get() ?
← →
Piter © (2009-10-08 21:22) [8]ты не поверишь, но ini_get("error_reporting") - тоже начинает возвращать 0! (((
← →
McSimm © (2009-10-08 21:24) [9]это они напрасно :)
← →
Piter © (2009-10-08 21:24) [10]кстати, из твоего примера это тоже следует:
set_error_handler("myErrorHandler");
error_reporting(E_ALL);
@$a = $b;
function myErrorHandler($errno, $errstr, $errfile, $errline)
{
$e = ini_get("error_reporting");
var_dump($e);
}
Результат: string(1) "0"
← →
McSimm © (2009-10-08 21:25) [11]объяви свою константу ORIGINAL_ERROR_LEVEL в момент регистрации хендлера.
← →
Piter © (2009-10-08 21:26) [12]офигеть, это уже на какие-то мега-костыли похоже... Ради недопущеная принта стандартной функции они изменяют значение error_reporting()?! Получается так...
← →
Piter © (2009-10-08 21:32) [13]ну да, очевидное решение... Что-то я тупанул, столько времени потерял, пытаясь во всем этом разобраться блин..
Спасибо, Максим!
← →
Piter © (2009-10-08 21:57) [14]а если уж пошла такая пьянка насчет PHP... Вот есть вопрос - не могу определить логику.
Этот class Error в движке имеет метод display, который и выводит все накопленные ошибки на экран:class Error ...
...
public function display($error_reporting = NULL)
{
$errortype = array
(
E_ERROR => "Error",
E_WARNING => "Warning",
E_PARSE => "Parsing Error",
E_NOTICE => "Notice",
E_CORE_ERROR => "Core Error",
E_CORE_WARNING => "Core Warning",
E_COMPILE_ERROR => "Compile Error",
E_COMPILE_WARNING => "Compile Warning",
E_USER_ERROR => "User Error",
E_USER_WARNING => "User Warning",
E_USER_NOTICE => "User Notice",
E_STRICT => "Runtime Notice"
);
if (!isset($error_reporting))
{
$error_reporting = $this->ORIGINAL_ERROR_LEVEL;
}
foreach ($this->stack as $error)
{
if ( ($error[0] & $error_reporting) != $error[0] )
{
continue;
}
$errno = isset($errortype[$error[0]])
? $errortype[$error[0]]
: "Unknown error";
echo "".$errno.": ".$error[1]." in file ".$error[2].
" on line ".$error[3].""."<br />\n";
}
}
Но интересно - когда по замыслу создателей он должен вызываться? Создается он в одном месте:$Registry->Error = new Error(DEBUG);
Нигде больше по коду движка я не вижу строчек "$Registry->Error"
У самого класса есть деструктор:public function __destruct()
{
$this->display();
}
Соответственно, вопросы:
1) создать новый класс я понимаю так: "new ClassType", а как удалить существующий класс вручную?
2) если экземпляр класса не уничтожен, то PHP в конце обработки скрипта вызывает деструкторы всех этих объектов?
3) если вызывает - то в деструкторе класса может быть какой-то вывод, с помощью того же echo?
Если так не работает, то на что надеялись разработчики, когда они планировали выводишь накапливаемые ошибки:public function general($errno, $errmsg, $filename, $linenum, $vars)
{
$this->addStack($errno, $errmsg, $filename, $linenum);
}
Где интересно можно искать? Где вообще это можно сделать?
← →
McSimm © (2009-10-08 22:15) [15]
> а как удалить существующий класс вручную?
$instance = null
> вызывает деструкторы всех этих объектов?
да
> в деструкторе класса может быть какой-то вывод, с помощью
> того же echo?
конечно.
← →
Piter © (2009-10-08 22:31) [16]тогда нифига не понятно... Вот это весь код класса:
class Error
{
private $debug = FALSE;
private $stack = array();
private $ORIGINAL_ERROR_LEVEL = 0;
public function __construct($debug = FALSE)
{
$this->debug = (bool) $debug;
$this->ORIGINAL_ERROR_LEVEL = error_reporting();
// xdebug_disable();
}
public function __destruct()
{
$this->display();
}
public function general($errno, $errmsg, $filename, $linenum, $vars)
{
$this->addStack($errno, $errmsg, $filename, $linenum);
}
public function pear($PEAR_Error)
{
echo $PEAR_Error->message.BR;
if ($this->debug)
{
echo $PEAR_Error->userinfo.BR;
}
else
{
echo "<!-- ".$PEAR_Error->userinfo." -->".LF;
}
exit;
}
public function display($error_reporting = NULL)
{
$errortype = array
(
E_ERROR => "Error",
E_WARNING => "Warning",
E_PARSE => "Parsing Error",
E_NOTICE => "Notice",
E_CORE_ERROR => "Core Error",
E_CORE_WARNING => "Core Warning",
E_COMPILE_ERROR => "Compile Error",
E_COMPILE_WARNING => "Compile Warning",
E_USER_ERROR => "User Error",
E_USER_WARNING => "User Warning",
E_USER_NOTICE => "User Notice",
E_STRICT => "Runtime Notice"
);
if (!isset($error_reporting))
{
$error_reporting = $this->ORIGINAL_ERROR_LEVEL;
}
foreach ($this->stack as $error)
{
if ( ($error[0] & $error_reporting) != $error[0] )
{
continue;
}
$errno = isset($errortype[$error[0]])
? $errortype[$error[0]]
: "Unknown error";
echo "".$errno.": ".$error[1]." in file ".$error[2].
" on line ".$error[3].""."<br />\n";
}
}
private function addStack($errno, $errmsg, $filename, $linenum)
{
$this->stack[] = array($errno, $errmsg, $filename, $linenum);
}
}
На метод general соответственно перенаправлены выводы ошибок стандартных:$Registry->Error = new Error(DEBUG);
set_error_handler(array($Registry->Error, "general"));
И все ок, ошибки добавляются в stack. Если я вызываю во время выполнения display - то они на экран выводятся. Но если вручную display не вызывать - по окочанию работы скрипта никаких ошибок нет.
Возможно, скрипт оканчивается по exit или die... Это влияет?
И куда тогда смотреть, почему в деструкторе не выводятся ошибки, хотя они есть...
← →
McSimm © (2009-10-08 22:53) [17]
> Возможно, скрипт оканчивается по exit или die... Это влияет?
нет.
Трудно сказать
буфферизация вывода используется?
смотришь результат в консоли или браузере?
← →
McSimm © (2009-10-08 23:07) [18]проверил, минимальный пример у меня работает.
← →
Piter © (2009-10-08 23:10) [19]буферизация вроде не используется... А как проверить?
Могу сказать, что если метод заменить на:public function general($errno, $errmsg, $filename, $linenum, $vars)
{
$this->addStack($errno, $errmsg, $filename, $linenum);
$this->display();
}
то ошибки на ура выводятся...
Есть команда, после которой echo ничего не сможет выводить на экран может? (((
Результат смотрю в браузере.
Если выводить сразу по мере поступления ошибки - все ок. Если дожидаться как в деструкторе вывод - фиг.Вообще ничего не выводится.
← →
McSimm © (2009-10-08 23:16) [20]
> Результат смотрю в браузере.
может там после </html> все ?
← →
Piter © (2009-10-08 23:49) [21]может быть!!! я в мозиле нажимаю "Исходный код страницы"
Он может не отображать то что после HTML, даже если получил?
← →
Piter © (2009-10-08 23:52) [22]хотя не, не вариант. Скрипт ведь 100% прерывался на строчке connect, там где-то exit стоит... Значит, даже если где-то пишется </html> - оно не смогло бы написаться...
← →
McSimm © (2009-10-09 00:25) [23]ну, если, например, используется буферизирующий шаблонизатор какой-нибудь... там всякое может быть.
по Fatal Error при каких-то условиях может тихо умереть, без вывода.
← →
McSimm © (2009-10-09 00:27) [24]вот, кстати, если у класса $Registry в деструкторе произойдет Fatal, то вроде бы все именно так и будет происходить - никакого вывода о фатале, никакого вызова деструтора для Error
← →
Piter © (2009-10-09 01:39) [25]да класс registry вроде очень простой:
<?php
class Registry
{
private $data = array();
static public function instance()
{
static $instance;
if (!isset($instance))
{
$instance = new Registry();
}
return $instance;
}
public function __get($name)
{
return @$this->data[$name];
}
public function __set($name, $value)
{
$this->data[$name] = $value;
}
}
?>
← →
Piter © (2009-10-09 01:41) [26]кстати, я не понимаю когда пишут подавление... Вот почему здесь так:
@$this->data[$name];
а не например так:
$this->@data[$name];
← →
McSimm © (2009-10-09 01:55) [27]Тут в большей мере, наверное, привычка и читабельность, чем какие-либо программные критерии.
(Лучше вообще не использовать.)
Страницы: 1 вся ветка
Форум: "Прочее";
Текущий архив: 2009.12.06;
Скачать: [xml.tar.bz2];
Память: 0.54 MB
Время: 0.005 c