错误处理函数

参见

另请参见 syslog().

目录

添加注释

用户贡献的注释 9 个注释

tracerdx at tracerdx dot com
18 年前
我一直在看到错误类型/错误编号作为数组的限定列表;在用户注释和手册本身中。例如,在此手册条目中的示例中,当尝试在错误报告中为变量跟踪分离行为时

<?php //...

// 将保存变量跟踪的错误集
$user_errors = array(E_USER_ERROR, E_USER_WARNING, E_USER_NOTICE);

// 稍后...

if (in_array($errno, $user_errors)) {
//... 无论什么
}

//... ?>

我一直认为 PHP 错误代码值是按位标志值。按位掩码会更好吗?因此,我建议一个稍微好一点的方法
<?php //...

$user_errors = E_USER_ERROR | E_USER_WARNING | E_USER_NOTICE;

//... 等等...

if ($errno & $user_errors) {
//... 无论什么
}

//... ?>
对于那些不喜欢在 if 语句中使用整数作为条件的人

<?php
if (($errno & $user_errors) > 0) {
//... 无论什么
}
?>

我认为这比使用 _另一个_ array() 结构和 in_array() 效率更高。

如果我错了,并且 E_* 常量不应该以这种方式使用(即,不能保证常量是按位的,这将很奇怪,因为这就是它们在 php.ini 文件中的设置方式),那么请删除我。我只是不明白为什么应该使用数组,而按位比较会起作用,考虑到按位方法应该效率更高得多。
ptah at se dot linux dot org
19 年前
仅限 PHP5(仅在 php5.0 中测试)。

如果你出于某种原因更喜欢异常而不是错误,并且你的自定义错误处理程序 (set_error_handler) 将错误包装到异常中,那么你必须小心你的脚本。

因为如果你不是仅仅调用异常处理程序,而是抛出异常,并且有一个自定义异常处理程序 (set_exception_handler)。如果在该异常处理程序中触发了错误,你将收到一个奇怪的错误
"致命错误:在 Unknown 上的第 0 行抛出异常而没有堆栈帧"

这个错误不是特别信息丰富,是吗?:)

下面的示例将导致此错误。
<?php
class PHPErrorException extends Exception
{
private
$context = null;
public function
__construct
($code, $message, $file, $line, $context = null)
{
parent::__construct($message, $code);
$this->file = $file;
$this->line = $line;
$this->context = $context;
}
};

function
error_handler($code, $message, $file, $line) {
throw new
PHPErrorException($code, $message, $file, $line);
}

function
exception_handler(Exception $e)
{
$errors = array(
E_USER_ERROR => "User Error",
E_USER_WARNING => "User Warning",
E_USER_NOTICE => "User Notice",
);

echo
$errors[$e->getCode()].': '.$e->getMessage().' in '.$e->getFile().
' on line '.$e->getLine()."\n";
echo
$e->getTraceAsString();
}

set_error_handler('error_handler');
set_exception_handler('exception_handler');

// 抛出具有/未知/错误代码的异常。
throw new Exception('foo', 0);
?>

但是,有一个简单的解决方案,因为这只是代码草率造成的。
比如,从 error_handler 中直接调用 exception_handler,而不是抛出异常。这不仅解决了这个问题,而且速度更快。虽然这会导致打印一个 `常规` 未处理的异常,并且如果只打算使用“设计”的错误消息,那么这不是最终的解决方案。

那么,该怎么办?确保 exception_handlers 中的代码不会导致任何错误!在这种情况下,一个简单的 isset() 就可以解决这个问题。

此致,C-A B。
shawing at gmail dot com
19 年前
虽然 root 用户写入文件 'error_log' 和 'access_log',但 Apache 用户必须拥有 'error_log = filename' 所引用的文件,否则不会写入任何日志条目。

; 来自 php.ini
; 将错误记录到指定文件。
error_log = /usr/local/apache/logs/php.errors

[root@www logs]$ ls -l /usr/local/apache/logs/php.errors
-rw-r--r-- 1 nobody root 27K Jan 27 16:58 php.errors
Stephen
17 年前
如果你使用 PHP 作为 Apache 模块,你的默认行为可能是将 PHP 错误消息写入 Apache 的错误日志。这是因为 error_log .ini 指令可能设置为等于 "error_log",这也是 Apache 错误日志的名称。我认为这是故意的。

但是,如果你愿意,可以通过简单地为 error_log 设置不同的值来将 Apache 错误与 PHP 错误分开。我将我的写入 /var/log 文件夹。
mortonda at dgrmm dot net
17 年前
请注意,这里列出的示例代码在每次调用时都会调用 date()。如果您有一个复杂的源代码库,经常调用自定义错误处理程序,最终可能会花费相当长的时间。我在一些代码上运行了一个分析器,发现 50% 的时间都花在了此错误处理程序中的 date 函数上。
theotek AT nowhere DOT org
18 年前
在错误处理函数中使用 debug_backtrace() 是完全可能的。请看这里

<?php
set_error_handler
('errorHandler');

function
errorHandler( $errno, $errstr, $errfile, $errline, $errcontext)
{
echo
'Into '.__FUNCTION__.'() at line '.__LINE__.
"\n\n---ERRNO---\n". print_r( $errno, true).
"\n\n---ERRSTR---\n". print_r( $errstr, true).
"\n\n---ERRFILE---\n". print_r( $errfile, true).
"\n\n---ERRLINE---\n". print_r( $errline, true).
"\n\n---ERRCONTEXT---\n".print_r( $errcontext, true).
"\n\nBacktrace of errorHandler()\n".
print_r( debug_backtrace(), true);
}

function
a( )
{
//echo "a()'s backtrace\n".print_r( debug_backtrace(), true);
asdfasdf; // oops
}

function
b()
{
//echo "b()'s backtrace\n".print_r( debug_backtrace(), true);
a();
}

b();
?>

输出

<raw>

Into errorhandler() at line 9

---ERRNO---
8

---ERRSTR---
Use of undefined constant asdfasdf - assumed 'asdfasdf'

---ERRFILE---
/home/theotek/test-1.php

---ERRLINE---
23

---ERRCONTEXT---
Array
(
)

Backtrace of errorHandler()
Array
(
[0] => Array
(
[function] => errorhandler
[args] => Array
(
[0] => 8
[1] => Use of undefined constant asdfasdf - assumed 'asdfasdf'
[2] => /home/theotek/test-1.php
[3] => 23
[4] => Array
(
)

)

)

[1] => Array
(
[file] => /home/theotek/test-1.php
[line] => 23
[function] => a
)

[2] => Array
(
[file] => /home/theotek/test-1.php
[line] => 30
[function] => a
[args] => Array
(
)

)

[3] => Array
(
[file] => /home/theotek/test-1.php
[line] => 33
[function] => b
[args] => Array
(
)

)

)

</raw>

因此,回溯数组的第一个成员并不令人意外,除了缺少“file”和“line”成员。

回溯的第二个成员似乎是 zend 引擎内部的钩子,用于触发错误。

其他成员是正常的回溯。
jbq at caraldi dot com
16 年前
关于 error_log 在使用 syslog 配置时的说明:syslog() 调用使用 NOTICE 严重级别。
Anonymous
19 年前
在 php.ini 中配置错误日志文件时,可以使用绝对路径或相对路径。相对路径将根据生成脚本的位置解析,您将在每个包含脚本的目录中获得日志文件。如果您希望所有错误消息都发送到同一个文件,请使用该文件的绝对路径。

在一些应用程序开发方法中,存在应用程序根目录的概念,用“/”表示(即使在 Windows 上也是如此)。但是,PHP 似乎没有这个概念,在日志文件路径中使用“/”作为初始字符会在 Windows 上产生奇怪的行为。

如果您在 Windows 上运行,并且在 php.ini 中设置了

error_log = "/php_error.log"

您将获得一些,但不是全部的错误消息。该文件将出现在

c:\php_error.log

并将包含内部生成的错误消息,使其看起来错误日志记录正在正常工作。但是,error_log() 请求的日志消息不会出现在这里,或任何其他地方,使其看起来包含它们的代码没有被处理。

显然,在 Windows 上,内部生成的错误将解释“/”为“C:\”(或者如果您在其他地方安装了 Windows,则可能是不同的驱动器 - 我还没有测试过)。但是,error_log 进程显然找不到“/” - 这可以理解 - 并且消息会静默地被丢弃。
petrov dot michael () gmail com
17 年前
我发现,在强制 display_errors 为 off 的服务器上,调试语法错误非常不方便,因为它们会导致致命启动错误。我使用了以下方法来绕过此限制

语法错误位于文件“syntax.php”中,因此我创建了一个文件“syntax.debug.php”,代码如下

<?php
error_reporting
(E_ALL);
ini_set('display_errors','On');

include(
'syntax.php');
?>

保证 5 行文件没有错误,允许 PHP 在包含以前导致致命启动错误的文件之前执行其中的指令。现在,那些致命启动错误变成了运行时致命错误。
To Top