mar*_*rio 11 php error-reporting
有哪些更好的方法可以避免isset()应用程序逻辑中的大量内容,并且在需要时保留查看调试消息(E_NOTICE)的能力?
首先推定:E_NOTICE不是错误,它是用词不当,实际上应该是E_DEBUG.然而,虽然这对于未设置的变量(PHP仍然是脚本语言)是正确的,但是一些文件系统函数等也会抛出它们.因此,需要开发 E_NOTICEs.
然而,并非所有调试通知都是有用的,这就是为什么在整个应用程序逻辑中引入isset()和@ 是一个常见的(不幸的)PHP习惯.isset/empty肯定有很多有效的用例,但总的来说它似乎是语法盐,实际上可能阻碍调试.
这就是我目前使用error_reporting书签和哑开/关开关的原因:
// javascript:(function(){document.cookie=(document.cookie.match(/error_reporting=1/)?'error_reporting=0':'error_reporting=1')})()
if (($_SERVER["REMOTE_ADDR"] == "127.0.0.1")
and $_COOKIE["error_reporting"])
{
error_reporting(E_ALL|E_STRICT);
}
else {/* less */}
Run Code Online (Sandbox Code Playgroud)
然而,这仍然让我有一个问题,即一旦启用就有太多通知来搜索.作为解决方法,我可以使用@ error suppress运算符.与isset()不同,它不会完全终止调试选项,因为自定义错误处理程序仍然可以接收抑制的E_NOTICE.因此,将预期的调试通知与潜在问题分开可能会有所帮助.
然而,这同样令人不满意.因此问题.有没有人使用或知道更复杂的PHP错误处理程序.我在想象:
当然,某些框架必须已经有这样的用户错误处理程序.
哦,我有人请帮助改写这个.冗长的解释失败了.
可以开发一个永远不会发出任何E_NOTICE的大型PHP应用程序.您所要做的就是避免发出通知的所有情况,其中绝大多数是未初始化的变量和非存在的数组键.不幸的是,这与您希望避免isset()- 并且通过扩展array_key_exists()- 的冲突,因为它们是为处理该确切问题而设计的.
充其量,您可以通过精心构建框架来最大限度地减少使用.这通常意味着(例如)输入层,该输入层被告知GET期望什么变量以及默认缺失的变量.这样,特定于页面的代码将始终具有要查看的值.通常,这是一种可以应用于各种API的有价值的技术.但我怀疑这是否应该是一个高优先级的设计目标.
与其他一些语言不同,PHP区分不存在的变量并且通常包含"空"值(通常null).它可能是早期版本的设计工件,但它仍然存在,所以你无法真正避免它.
我isset()只使用$_GET和$_SERVER变量,其中数据来自我的应用程序控制之外.当我没有时间编写适当的OOP解决方案以避免它时,我在其他情况下使用它,但我确信在大多数情况下(如果不是所有地方)都可以避免它.例如,最好使用类而不是关联数组,这样就不需要检查是否存在数组键.
我的建议是:
@操作员.xdebug.collect_params=4以及xdebug.show_local_vars=on配置参数).其次,它可以@使用xdebug.scream=1配置值禁用运算符.您也可以使用Xdebug进行性能分析和代码覆盖率分析.这是您的开发机器必备的.我在PHP手册中使用了该示例的修改版本:
<?php
//error_reporting(0);
set_error_handler("errorHandler");
function errorHandler($errno, $errstr, $errfile, $errline)
{
echo "errorHandler()<br />\n";
// filter out getImageSize() function with non existent files (because I'am avoiding using file_exists(), which is a costly operation)
if ( mb_stripos($errstr, 'getimagesize') !== false )
return true;
// filter out filesize() function with non existent files
if ( mb_stripos($errstr, 'filesize') !== false )
return true;
// consoleWriter is my class which sends the messages with FirePHP
if (class_exists('consoleWriter'))
consoleWriter::debug(array('errno'=>$errno, 'errstr'=>$errstr, 'errfile'=>$errfile, 'errline'=>$errline, 'trace'=>debug_backtrace()), "errorHandler");
switch ($errno) {
case E_USER_ERROR:
$out .= "<b>FATAL_ERROR</b> <i>$errno</i> $errstr<br />\n";
$out .= "Fatal error on line $errline in file $errfile";
echo "</script>$out"; // if we were in a script tag, then the print is not visible without this
//writeErrorLog($out);
echo "<pre>";
var_export(debug_backtrace());
echo "</pre>";
exit(1);
break;
case E_USER_WARNING:
$out .= "<b>WARNING</b> <i>$errno</i> $errstr<br />\n";
$out .= "On line $errline in file $errfile<br />\n";
break;
case E_USER_NOTICE:
$out .= "<b>NOTICE</b> <i>$errno</i> $errstr<br />\n";
$out .= "On line $errline in file $errfile<br />\n";
break;
default:
$out .= "<b>Unknown</b> <i>$errno</i> $errstr<br />\n";
$out .= "On line $errline in file $errfile<br />\n";
break;
}
if (!class_exists('consoleWriter'))
echo $out;
//writeErrorLog($out);
//addJGrowlMessage($out);
// Don't execute PHP internal error handler
return true;
}
function testNotice($a)
{
echo $a;
}
testNotice();
Run Code Online (Sandbox Code Playgroud)
还有一个建议是不要?>在php-only文件末尾使用结束标记,因为它可能会导致headers already sent默认情况下禁用输出缓冲的配置出错.
好吧,如果您等待 PHP 7,您将可以使用空合并三元运算符,除了拥有现有的最酷的运算符名称(我将我的下一个孩子命名为“Null Coalesce”)之外,它还可以让您这样做这:
$var = $some_array[$some_value] ?? "default value";
Run Code Online (Sandbox Code Playgroud)
它取代了无处不在的(而且丑陋的)
$var = isset( $some_array[$some_value] ) ? $some_array[$some_value] : "default_value";
Run Code Online (Sandbox Code Playgroud)