我经常会尝试运行一个 PHP 脚本,然后返回一个空白屏幕。没有错误信息;只是一个空的屏幕。原因可能是一个简单的语法错误(错误的括号,缺少分号),或者一个失败的函数调用,或者完全是其他的东西。
很难弄清楚出了什么问题。我最终注释掉了代码,到处输入“echo”语句,等等,试图缩小问题的范围。但肯定有更好的方法,对吧?
有没有办法让 PHP 产生有用的错误消息,就像 Java 一样?
T_PAAMAYIM_NEKUDOTAYIM
。或者可能是 "must be an instance of integer, integer given"。
php.exe -l <your file name>
对于语法错误,您需要在 php.ini 中启用错误显示。默认情况下,这些是关闭的,因为您不希望“客户”看到错误消息。 Check this page 在 PHP 文档中获取有关 2 个指令的信息:error_reporting
和 display_errors
。 display_errors
可能是您要更改的那个。如果无法修改 php.ini,还可以在 .htaccess 文件中添加以下行:
php_flag display_errors on
php_value error_reporting 2039
您可能需要考虑为您的 PHP 版本为 error_reporting
使用 E_ALL 的值(如 Gumbo 所述)来获取所有错误。 more info
其他 3 项: (1) 您可以检查错误日志文件,因为它将包含所有错误(除非日志记录已被禁用)。 (2) 添加以下 2 行将帮助您调试不是语法错误的错误:
error_reporting(-1);
ini_set('display_errors', 'On');
(3) 另一种选择是使用在您键入时检查错误的编辑器,例如 PhpEd。 PhpEd 还带有一个调试器,可以提供更详细的信息。 (PhpEd 调试器与 xdebug 非常相似,并且直接集成到编辑器中,因此您可以使用 1 个程序来完成所有操作。)
卡特曼的link也很不错:http://www.ibm.com/developerworks/library/os-debug/
以下启用所有错误:
ini_set('display_startup_errors', 1);
ini_set('display_errors', 1);
error_reporting(-1);
另请参阅以下链接
http://php.net/manual/en/errorfunc.configuration.php#ini.display-errors
http://php.net/manual/en/errorfunc.configuration.php#ini.display-startup-errors
http://php.net/manual/en/function.error-reporting.php
ini_set
的第二个参数是一个字符串。
以下代码应显示所有错误:
<?php
// ----------------------------------------------------------------------------------------------------
// - Display Errors
// ----------------------------------------------------------------------------------------------------
ini_set('display_errors', 'On');
ini_set('html_errors', 0);
// ----------------------------------------------------------------------------------------------------
// - Error Reporting
// ----------------------------------------------------------------------------------------------------
error_reporting(-1);
// ----------------------------------------------------------------------------------------------------
// - Shutdown Handler
// ----------------------------------------------------------------------------------------------------
function ShutdownHandler()
{
if(@is_array($error = @error_get_last()))
{
return(@call_user_func_array('ErrorHandler', $error));
};
return(TRUE);
};
register_shutdown_function('ShutdownHandler');
// ----------------------------------------------------------------------------------------------------
// - Error Handler
// ----------------------------------------------------------------------------------------------------
function ErrorHandler($type, $message, $file, $line)
{
$_ERRORS = Array(
0x0001 => 'E_ERROR',
0x0002 => 'E_WARNING',
0x0004 => 'E_PARSE',
0x0008 => 'E_NOTICE',
0x0010 => 'E_CORE_ERROR',
0x0020 => 'E_CORE_WARNING',
0x0040 => 'E_COMPILE_ERROR',
0x0080 => 'E_COMPILE_WARNING',
0x0100 => 'E_USER_ERROR',
0x0200 => 'E_USER_WARNING',
0x0400 => 'E_USER_NOTICE',
0x0800 => 'E_STRICT',
0x1000 => 'E_RECOVERABLE_ERROR',
0x2000 => 'E_DEPRECATED',
0x4000 => 'E_USER_DEPRECATED'
);
if(!@is_string($name = @array_search($type, @array_flip($_ERRORS))))
{
$name = 'E_UNKNOWN';
};
return(print(@sprintf("%s Error in file \xBB%s\xAB at line %d: %s\n", $name, @basename($file), $line, $message)));
};
$old_error_handler = set_error_handler("ErrorHandler");
// other php code
?>
使用此代码生成空白页的唯一方法是在关闭处理程序中出现错误时。我从我自己的 cms 复制并粘贴了它,没有测试它,但我确信它可以工作。
ShutdownHandler
中说错误。基本上,这是代替正确错误处理的权宜之计。
E_NOTICE
错误?
您可以在要调试的文件中包含以下行:
error_reporting(E_ALL);
ini_set('display_errors', '1');
这会覆盖 php.ini 中的默认设置,这只会让 PHP 将错误报告到日志中。
错误和警告通常出现在 ....\logs\php_error.log
或 ....\logs\apache_error.log
中,具体取决于您的 php.ini 设置。
有用的错误也经常被定向到浏览器,但由于它们不是有效的 html,它们不会显示出来。
所以"tail -f
”你的日志文件,当你得到一个空白屏幕时,使用 IE 的“查看”->“源”菜单选项来查看原始输出。
php_flag display_errors 1
的 .htaccess 文件。
PHP 配置
php.ini 中的 2 个条目指示错误的输出:
显示错误错误报告
在生产中,display_errors
通常设置为 Off
(这是一件好事,因为通常不希望在生产站点中显示错误!)。
但是,在开发中,它应该设置为 On
,以便显示错误。 检查!
error_reporting
(自 PHP 5.3 起)默认设置为 E_ALL & ~E_NOTICE & ~E_STRICT & ~E_DEPRECATED
(意思是显示除通知、严格标准和弃用通知外的所有内容)。如有疑问,请将其设置为 E_ALL
以显示所有错误。 检查!
哇哇!没有检查!我无法更改我的 php.ini!
真可惜。通常共享主机不允许更改其 php.ini 文件,因此该选项不可用。但不要害怕!我们有other options!
运行时配置
在所需的脚本中,我们可以在运行时更改 php.ini 条目!意思是,它会在脚本运行时运行!甜的!
error_reporting(E_ALL);
ini_set("display_errors", "On");
这两行将与上面更改 php.ini 条目的效果相同!惊人的!
我仍然收到空白页/500 错误!
这意味着脚本甚至还没有运行!当您有语法错误时,通常会发生这种情况!
由于语法错误,脚本甚至无法运行。它在编译时失败,这意味着它将使用 php.ini 中的值,如果您没有更改,可能不允许显示错误。
错误日志
此外,PHP 默认记录错误。在共享主机中,它可能位于专用文件夹中或与有问题的脚本位于同一文件夹中。
如果您有权访问 php.ini,则可以在 error_log
条目下找到它。
include
有错误的 php 文件。
我总是在 php 脚本的最顶部使用这种语法。
ini_set('error_reporting', E_ALL);
ini_set('display_errors', 'On'); //On or Off
有一个非常有用的扩展名为“xdebug”,它也可以让您的报告变得更好。
对于快速的动手故障排除,我通常建议在这里:
error_reporting(~0); ini_set('display_errors', 1);
放在正在排除故障的脚本的开头。这并不完美,完美的变体是您也在 php.ini
中启用它,并在 PHP 中记录错误以捕获语法和启动错误。
此处列出的设置显示所有错误、通知和警告,包括严格的,无论 PHP 版本。
接下来要考虑的事情:
安装 Xdebug 并使用您的 IDE 启用远程调试。
另见:
错误报告(PHP 的正确方法。)
预定义常量文档
error_reporting()文档
display_errorsDocs
可以注册一个钩子以使最后一个错误或警告可见。
function shutdown(){
var_dump(error_get_last());
}
register_shutdown_function('shutdown');
将此代码添加到 index.php 的开头将帮助您调试问题。
如果你超级酷,你可以试试:
$test_server = $_SERVER['SERVER_NAME'] == "127.0.0.1" || $_SERVER['SERVER_NAME'] == "localhost" || substr($_SERVER['SERVER_NAME'],0,3) == "192";
ini_set('display_errors',$test_server);
error_reporting(E_ALL|E_STRICT);
这只会在您在本地运行时显示错误。它还为您提供了 test_server 变量,以便在其他适当的地方使用。
在脚本运行之前发生的任何错误都不会被捕获,但对于我犯的 99% 的错误,这不是问题。
$_SERVER['REMOTE_HOST']
来检查客户端是否是您。
在页面顶部选择一个参数
error_reporting(E_ERROR | E_WARNING | E_PARSE);
这是加载与运行时配置的问题
重要的是要认识到在 compile 或 parsing 步骤期间会发生语法错误或解析错误,这意味着 PHP 甚至在它有机会执行任何你的代码。因此,如果您在运行时修改 PHP 的 display_errors
配置(这包括从在代码中使用 ini_set
到使用运行时配置文件 .htaccess 的任何内容),那么只有默认的加载的配置设置 正在发挥作用。
如何在开发中始终避免 WSOD
为避免 WSOD,您需要确保 加载的配置文件 已打开 display_errors
且 error_reporting
设置为 -1
(这是等效的 E_ALL,因为它确保所有位都无论您运行的是哪个版本的 PHP,都会打开)。不要硬编码 E_ALL 的常量值,因为该值会在不同版本的 PHP 之间发生变化。
加载的配置是您加载的 php.ini
文件或您的 apache.conf
或 httpd.conf
或 virtualhost 文件。这些文件仅在启动阶段读取一次(例如,当您第一次启动 apache httpd 或 php-fpm 时)并且仅被运行时配置更改覆盖。确保加载的配置文件中的 display_errors = 1
和 error_reporting = -1
确保您永远不会看到 WSOD,无论在运行时更改(如 ini_set('display_errors', 1);
或 error_reporting(E_ALL);
)之前发生的语法或解析错误如何可以发生。
如何找到您的 (php.ini) 加载的配置文件
要找到您加载的配置文件,只需使用以下代码创建一个新的 PHP 文件...
<?php
phpinfo();
然后将您的浏览器指向那里并查看 加载的配置文件 和 已解析的其他 .ini 文件,它们通常位于 phpinfo()
的顶部,其中包含指向所有加载的配置文件。
如果您看到 (none)
而不是文件,则表示您在 配置文件 (php.ini) 路径 中没有 php.ini。因此,您可以 download the stock php.ini bundled with PHP from here 并将其作为 php.ini 复制到您的配置文件路径,然后确保您的 php 用户具有足够的权限来读取该文件。您需要重新启动 httpd 或 php-fpm 才能加载它。记住,这是与 PHP 源捆绑在一起的 development php.ini 文件。所以请不要在生产中使用它!
只是不要在生产中这样做
这确实是在开发中避免 WSOD 的最佳方法。任何建议您将 ini_set('display_errors', 1);
或 error_reporting(E_ALL);
放在 PHP 脚本顶部或使用 .htaccess 的人都不会在发生语法或解析错误时帮助您避免 WSOD(就像您在此处的情况一样) ) 如果您加载的配置文件已关闭 display_errors
。
许多人(以及 PHP 的普通安装)将使用默认关闭 display_errors
的生产 ini 文件,这通常会导致您在此处遇到同样的挫败感。因为 PHP 在启动时已经将其关闭,然后遇到语法或解析错误,并且没有输出任何内容。您希望您的 PHP 脚本顶部的 ini_set('display_errors',1);
应该避免这种情况,但如果 PHP 无法解析您的代码也没关系,因为它永远不会到达运行时。
要坚持这一点并使其舒适,您可以编辑您的 php.ini 文件。它通常存储在 /etc/php.ini
或 /etc/php/php.ini
中,但更多本地 php.ini
可能会覆盖它,具体取决于您的托管服务提供商的设置指南。检查顶部的 Loaded Configuration File
的 phpinfo()
文件,以确保最后加载哪个文件。
在该文件中搜索 display_errors。应该只有 3 个实例,其中 2 个被注释。
将未注释的行更改为:
display_errors = stdout
ini_set('display_errors', 1);
ini_set('display_startup_errors', 1);
error_reporting(E_ALL);
我不知道它是否会有所帮助,但这是我用于 php 项目的标准配置文件的一部分。即使在我自己的服务器上,我也不会过多地依赖 apache 配置。
我从来没有遇到过消失的错误问题,所以也许这里的一些东西会给你一个想法。
编辑显示APPLICATON_LIVE
/*
APPLICATION_LIVE will be used in process to tell if we are in a development or production environment. It's generally set as early as possible (often the first code to run), before any config, url routing, etc.
*/
if ( preg_match( "%^(www.)?livedomain.com$%", $_SERVER["HTTP_HOST"]) ) {
define('APPLICATION_LIVE', true);
} elseif ( preg_match( "%^(www.)?devdomain.net$%", $_SERVER["HTTP_HOST"]) ) {
define('APPLICATION_LIVE', false);
} else {
die("INVALID HOST REQUEST (".$_SERVER["HTTP_HOST"].")");
// Log or take other appropriate action.
}
/*
--------------------------------------------------------------------
DEFAULT ERROR HANDLING
--------------------------------------------------------------------
Default error logging. Some of these may be changed later based on APPLICATION_LIVE.
*/
error_reporting(E_ALL & ~E_STRICT);
ini_set ( "display_errors", "0");
ini_set ( "display_startup_errors", "0");
ini_set ( "log_errors", 1);
ini_set ( "log_errors_max_len", 0);
ini_set ( "error_log", APPLICATION_ROOT."logs/php_error_log.txt");
ini_set ( "display_errors", "0");
ini_set ( "display_startup_errors", "0");
if ( ! APPLICATION_LIVE ) {
// A few changes to error handling for development.
// We will want errors to be visible during development.
ini_set ( "display_errors", "1");
ini_set ( "display_startup_errors", "1");
ini_set ( "html_errors", "1");
ini_set ( "docref_root", "http://www.php.net/");
ini_set ( "error_prepend_string", "<div style='color:red; font-family:verdana; border:1px solid red; padding:5px;'>");
ini_set ( "error_append_string", "</div>");
}
error_reporting(E_ALL | E_STRICT);
ini_set('display_errors', 1);
ini_set('html_errors', 1);
此外,您可以使用 xdebug 获得更多详细信息。
我推荐 Nette Tracy 以更好地可视化 PHP 中的错误和异常:
https://i.stack.imgur.com/B1gSC.png
error_reporting(E_ALL | E_STRICT);
并在 php.ini 中开启显示错误
您可以在 PHP 中注册自己的 error handler。例如,将所有错误转储到文件可能会在这些晦涩难懂的情况下对您有所帮助。请注意,无论您当前的 error_reporting 设置为什么,都会调用您的函数。非常基本的例子:
function dump_error_to_file($errno, $errstr) {
file_put_contents('/tmp/php-errors', date('Y-m-d H:i:s - ') . $errstr, FILE_APPEND);
}
set_error_handler('dump_error_to_file');
从 PHP 中获取有用错误所需的两条关键线是:
ini_set('display_errors',1);
error_reporting(E_ALL);
正如其他贡献者所指出的,出于安全原因,这些默认情况下是关闭的。作为一个有用的提示 - 当您设置站点时,可以方便地为不同的环境进行切换,以便这些错误在您的本地和开发环境中默认为 ON。这可以通过以下代码来实现(最好在您的 index.php 或配置文件中,因此从一开始就处于活动状态):
switch($_SERVER['SERVER_NAME'])
{
// local
case 'yourdomain.dev':
// dev
case 'dev.yourdomain.com':
ini_set('display_errors',1);
error_reporting(E_ALL);
break;
//live
case 'yourdomain.com':
//...
break;
}
打开你的 php.ini,确保它设置为:
display_errors = On
重新启动您的服务器。
您可能还想尝试 PHPStorm 作为您的代码编辑器。当您在编辑器中键入时,它会发现许多 PHP 和其他语法错误。
如果您是 ubuntu 用户,请转到您的终端并运行此命令
sudo tail -50f /var/log/apache2/error.log
它将显示最近的 50 个错误。 apache2 有一个错误文件 error.log
,它记录了所有错误。
要打开完整的错误报告,请将其添加到您的脚本中:
error_reporting(E_ALL);
这会导致出现最小的警告。而且,以防万一:
ini_set('display_errors', '1');
将强制显示错误。这应该在生产服务器中关闭,但不是在您开发时。
“错误”是开发人员了解错误并解决错误以使系统完美运行的最有用的东西。
PHP 提供了一些更好的方法来了解开发人员为什么以及他们的代码出现错误的位置,因此通过了解这些错误,开发人员可以在许多方面改进他们的代码。
在脚本顶部编写以下两行以获取所有错误消息的最佳方法:
error_reporting(E_ALL);
ini_set("display_errors", 1);
在 IDE 中使用 xdebug 等调试器工具的另一种方法。
除了这里所有精彩的答案,我想特别提及 MySQLi 和 PDO 库。
为了...
总是看到与数据库相关的错误,并避免检查方法的返回类型以查看是否出现问题
最好的选择是将库配置为 throw exceptions。
MySQLi
在脚本顶部附近添加它
mysqli_report(MYSQLI_REPORT_ERROR | MYSQLI_REPORT_STRICT);
最好在使用 new mysqli()
或 mysqli_connect()
之前放置。
PDO
在您的连接实例上将 PDO::ATTR_ERRMODE
属性设置为 PDO::ERRMODE_EXCEPTION
。您可以在构造函数中执行此操作
$pdo = new PDO('driver:host=localhost;...', 'username', 'password', [
PDO::ATTR_ERRMODE => PDO::ERRMODE_EXCEPTION
]);
或创建后
$pdo->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);
您可以启用完整的错误报告(包括通知和严格的消息)。有些人觉得这太冗长了,但值得一试。在 php.ini 中将 error_reporting
设置为 E_ALL | E_STRICT
。
error_reporting = E_ALL | E_STRICT
E_STRICT
将通知您有关已弃用的功能,并为您提供有关执行某些任务的最佳方法的建议。
如果您不想要通知,但发现其他消息类型有帮助,请尝试排除通知:
error_reporting = (E_ALL | E_STRICT) & ~E_NOTICE
还要确保在 php.ini 中启用了 display_errors
。如果您的 PHP 版本早于 5.2.4,请将其设置为 On
:
display_errors = "On"
如果您的版本是 5.2.4 或更高版本,请使用:
display_errors = "stderr"
除了 error_reporting 和 display_errors ini 设置之外,您还可以从 Web 服务器的日志文件中获取语法错误。当我开发 PHP 时,我将开发系统的 Web 服务器日志加载到我的编辑器中。每当我测试一个页面并得到一个空白屏幕时,日志文件就会过时,我的编辑器会询问我是否要重新加载它。当我这样做时,我跳到底部并且存在语法错误。例如:
[Sun Apr 19 19:09:11 2009] [error] [client 127.0.0.1] PHP Parse error: syntax error, unexpected T_ENCAPSED_AND_WHITESPACE, expecting T_STRING or T_VARIABLE or T_NUM_STRING in D:\\webroot\\test\\test.php on line 9
这个答案是冗余部门为您带来的。
ini_set() / php.ini / .htaccess / .user.ini 设置 display_errors 和 error_reporting 现在已经充分覆盖了。但只是回顾一下何时使用哪个选项:ini_set() 和 error_reporting() 仅适用于运行时错误。 php.ini 应该主要针对开发设置进行编辑。 (Web 服务器和 CLI 版本通常具有不同的 php.ini) .htaccess 标志仅适用于过时的设置(寻找新的主机!管理良好的服务器更便宜。) .user.ini 是现代设置(FCGI/FPM)的部分 php.ini作为运行时错误的粗略替代方法,您可以经常使用: set_error_handler("var_dump"); // 忽略 error_reporting 和 `@` 抑制 error_get_last() 当 error_display 被禁用时,可用于检索最后一次运行时通知/警告/错误。 $php_errormsg 是一个超局部变量,它还包含最后一条 PHP 运行时消息。 isset() 消失了!我知道这会让很多人不快,但是新手不应该使用 isset 和 empty。您可以在验证代码正常工作后添加通知抑制。但以前从来没有。我们最近收到的很多“某事不起作用”的问题都是由于拼写错误造成的,例如: if(isset($_POST['sumbit'])) # ↑↑ 如果你的代码是到处都是 isset/empty/array_keys_exists。有时使用@ 更明智,因此通知和警告至少会出现在日志中。 assert_options(ASSERT_ACTIVE|ASSERT_WARNING);获取 assert() 部分的警告。 (相当少见,但更熟练的代码可能包含一些。)PHP7 也需要 php.ini 中的 zend.assertions=1。声明(严格类型=1);将 PHP 转换为严格类型的语言并不能修复很多逻辑错误,但它绝对是用于调试目的的一种选择。 PDO/MySQLi 和@Phil 已经提到了 PDO/MySQLi 错误报告选项。当然,其他数据库 API 也存在类似的选项。 json_last_error() + json_last_error_msg 用于 JSON 解析。 preg_last_error() 用于正则表达式。 CURLOPT_VERBOSE 要调试 curl 请求,您至少需要 CURLOPT_VERBOSE。 shell/exec() 同样,shell 命令执行本身不会产生错误。您总是需要 2>&1 并查看 $errno。
不定期副业成功案例分享
E_ERROR | E_WARNING | E_PARSE | E_CORE_ERROR | E_CORE_WARNING | E_COMPILE_ERROR | E_COMPILE_WARNING | E_USER_ERROR | E_USER_WARNING | E_USER_NOTICE
的值。请参阅docs.php.net/manual/en/errorfunc.constants.php