E_NOTICE?== E_DEBUG,避免使用更复杂的error_handler的isset()和@

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错误处理程序.我在想象:

  • 输出未过滤的错误/警告/通知(使用CSS绝对定位?)
  • 和AJAX-whatnot允许客户端检查和抑制
  • 但也保存了预期和" 已批准 "通知或警告的过滤列表.

当然,某些框架必须已经有这样的用户错误处理程序.

  • 基本上我对警告/通知管理很感兴趣.
  • 完全没有E_NOTICE抑制.
  • E_NOTICES 通缉.只是少了一些.默认情况下突出显示我可能关心的,而不是预期的.
  • 如果我在没有?order =参数的情况下运行,则会出现预期的NOTICE.由于预期,我不需要多次通知.
  • 但是,当处于完全调试模式时,我希望通过所述调试通知的存在(或更有趣的缺失)来看到存在未定义的变量. - >这就是我认为它们的用途.避免使用isset带来语言隐含的打印语句.
  • 还要意识到这是关于普通PHP表单处理语义适用的用例,而不是严格必须的应用程序区域.

哦,我有人请帮助改写这个.冗长的解释失败了.

sta*_*san 9

可以开发一个永远不会发出任何E_NOTICE的大型PHP应用程序.您所要做的就是避免发出通知的所有情况,其中绝大多数是未初始化的变量和非存在的数组键.不幸的是,这与您希望避免isset()- 并且通过扩展array_key_exists()- 的冲突,因为它们是为处理该确切问题而设计的.

充其量,您可以通过精心构建框架来最大限度地减少使用.这通常意味着(例如)输入层,该输入层被告知GET期望什么变量以及默认缺失的变量.这样,特定于页面的代码将始终具有要查看的值.通常,这是一种可以应用于各种API的有价值的技术.但我怀疑这是否应该是一个高优先级的设计目标.

与其他一些语言不同,PHP区分不存在的变量并且通常包含"空"值(通常null).它可能是早期版本的设计工件,但它仍然存在,所以你无法真正避免它.

  • 啊......我错了,但我想我知道你要去哪里.如果我是对的,你正在尝试使用一种不适用于PHP的开发技术,这就是你遇到麻烦的原因.IME,更好的方法是始终将'E_NOTICE`*留在*上并修复Notices where和your find.是的,这意味着编码更具防御性,是的,它意味着在依赖可能不存在的变量(但你可以*检查一次并设置默认值)之前,`isset()`调用的可能森林.换句话说,这意味着你总是*在开发过程中寻找不存在的变量. (4认同)

Ist*_*ros 6

isset()只使用$_GET$_SERVER变量,其中数据来自我的应用程序控制之外.当我没有时间编写适当的OOP解决方案以避免它时,我在其他情况下使用它,但我确信在大多数情况下(如果不是所有地方)都可以避免它.例如,最好使用类而不是关联数组,这样就不需要检查是否存在数组键.

我的建议是:

  • 避免使用@操作员.
  • 使用Xdebug.首先,它打印出易于阅读且易于注意的关于每个通知/ warnig的消息,并且它会在异常上打印出非常有用的堆栈跟踪(您可以将其配置为打印出每个方法参数和每个局部变量(xdebug.collect_params=4以及xdebug.show_local_vars=on配置参数).其次,它可以@使用xdebug.scream=1配置值禁用运算符.您也可以使用Xdebug进行性能分析和代码覆盖率分析.这是您的开发机器必备的.
  • 对于调试,我也使用FirePHP,因为它可以与Firebug一起使用,并且能够将消息打印到Firebug控制台,因此它也可以用于AJAX调试.
  • 使用自定义错误处理程序,您可以捕获并过滤任何错误和警告,您可以将它们记录到文件中或使用FirePHP显示它们,或者您可以使用例如jGrowlGritter在网页上很好地显示它们.

我在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默认情况下禁用输出缓冲的配置出错.


Tom*_*ger 3

好吧,如果您等待 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)

  • (根据当前的邮件列表思考,5.7 甚至可能会向后移植一些东西。[由于所有的弃用,PHP7 部署不太可能在十年内广泛普及..]) (2认同)