2015-07-13 84 views
4

还有就是可以发出警告,由于对错误有可能在正常运行的情况发生的条件,如许多好的旧程序功能:fopen()mail()oci_connect() ...正确的方式来处理不可避免的警告

  • most obvious workaround据说是昂贵的,并具有隐藏一切的副作用:

    echo @file_get_contents(oops_forgot_dollar); 
    
  • 自定义错误处理程序看起来Ø verkill:

    private function warningHandler($errno, $errstr, $errfile, $errline/*, array $errcontext*/){ 
        if(error_reporting()===0){ 
         return false; 
        }else{ 
         throw new ErrorException($errstr, 0, $errno, $errfile, $errline); 
        } 
    } 
    
    // .... 
    
    try{ 
        set_error_handler('CSVLoader::warningHandler', E_WARNING); 
        $this->fp = fopen($filename, 'r'); 
        restore_error_handler(); 
    
        $this->readData(); 
    }catch(ErrorException $e){ 
        restore_error_handler(); 
        throw new CSVLoaderException("Could not open file: {$e->getMessage()}"); 
    } 
    
  • 又让警告穿过即使在一个正确配置的服务器是烦人:

    • 研究与开发他们在荒郊野外显示并可以打破的东西
    • 生产他们用无用的数据淹没错误日志

建议的做法是什么? PHP专家如何处理它?

+1

通常由CH在进行函数调用之前设置正确的条件,即用'file_get_contents',在调用之前做一个'is_readable'调用,这不会引发错误,但会让您深入了解'file_get_contents'是否会出错 – naththedeveloper

+0

@ɴᴀᴛʜ - 我不是很确信。您如何事先知道数据库服务器是否会接受连接?即使你变得固执并用'fsockopen()'模拟一个''''你会需要*更多*以前的检查以防''fsockopen()'也触发警告。这种方法也意味着选择不使用像'file_get_contents()'这样的设备:任何读取文件的代码都需要大量的样板文件。 –

回答

1

error_log里是不是无用数据

我觉得它通常是很容易的继续,如果有一个小时的cron作业的最上面的那的error_log文件的人的电子邮件内容.....

不久,您将在适当的检查中添加代码库和排序的问题。

+1

我很欣赏你花时间撰写了答案,但我不确定你是否真的理解我的问题。想象一下,你维护一个库来发送电子邮件。当传出SMTP连接失败时,您的库会引发一个很好的'FooMailer \ TransportException'。它触发(并记录!)一个额外的不可捕捉的'E_WARNING'有什么意义?终端用户是否会觉得更合理,只是将邮件标记为未发送到他们的新闻通讯数据库中? –

+0

最终用户永远不会找到error_log或类似的帮助很多的消息 - 他们需要一个更有帮助的消息(“对不起,发生了一些非常糟糕的事情”,“您没有正确填写所有表单域)。” 如何检测你的错误是由你自己决定的,例外情况与检查返回值或其他值一样。 很显然,在设计你的应用程序/系统时,你知道某些东西可能会失败(发送简报到许多地址,并且可以在以后的日期重试),而其他事情是例外事件 - (例如数据库服务器已死) –

1

我做了一些流行的PHP框架和流行的Packagist包间快速肮脏的倾斜不科学的调查,发现这一点:

  • 错误抑制操作是合理的流行(笨,•奈特,斯威夫特梅勒,Yii的.. )。
  • 其他项目使用set_error_handler()投掷ErrorException或其他一些异常(Zend,Symfony,Laravel,PHPUnit,Psy ...)。大多数简单地使用项目范围的错误处理程序,一些(PHPMailer)在设置/恢复调用中包装特定的操作。
  • 一些其他项目显然只是不在乎(PHPExcel)。

我想说的是:

  • 如果你已经有了一个自定义的错误处理程序,它可能更好地利用它。
  • 否则,错误控制操作符可能会很好(但在开发该代码段时暂时删除它可能是一个好主意)。无论如何,所谓的不良表现doesn't seem to be a big deal *,尤其是,如果你正在做一个“慢”操作,比如打开一个数据库连接,套接字或文件。
  • 作为辩论,它可能在标签与空格相同的区域。

(*)我发现,比较@isset()并确定@很慢无尽的基准。真正发生的是isset()非常快 - 实际上是much faster that not using either


最后但并非最不重要的,因为性能的问题,我将分享我的第一家酿造基准一次更快速和肮脏的一个,没有一个适当的基准框架。请注意,我只是想试探迄今最坏的情况(所有的函数调用发出警示):在我的Windows 7盒

<?php 

error_reporting(-1); 
ini_set('display_errors', false); 
ini_set('log_errors', false); 


define('ITERATIONS', 10000); 


function warning_handler($errno, $errstr, $errfile, $errline/*, array $errcontext*/){ 
    throw new ErrorException($errstr, 0, $errno, $errfile, $errline); 
} 


echo sprintf('Running %s iterations on PHP/%s...' . PHP_EOL, number_format(ITERATIONS), phpversion()); 


$t0 = microtime(true); 
for($i=0; $i<ITERATIONS; $i++){ 
    fopen("FooA $i", 'r'); 
} 
echo sprintf('Raw:       % 6.3fs' . PHP_EOL, microtime(true) - $t0); 


$t0 = microtime(true); 
for($i=0; $i<ITERATIONS; $i++){ 
    @fopen("FooB $i", 'r'); 
} 
echo sprintf('@:       % 6.3fs' . PHP_EOL, microtime(true) - $t0); 


$t0 = microtime(true); 
for($i=0; $i<ITERATIONS; $i++){ 
    set_error_handler('warning_handler', E_WARNING); 
    try{ 
     fopen("FooC $i", 'r'); 
     restore_error_handler(); 
    }catch(ErrorException $e){ 
     restore_error_handler(); 
    } 
} 
echo sprintf('Local set_error_handler(): % 6.3fs' . PHP_EOL, microtime(true) - $t0); 


$t0 = microtime(true); 
set_error_handler('warning_handler', E_WARNING); 
for($i=0; $i<ITERATIONS; $i++){ 
    try{ 
     fopen("FooD $i", 'r'); 
    }catch(ErrorException $e){ 
    } 
} 
restore_error_handler(); 
echo sprintf('General set_error_handler(): % 6.3fs' . PHP_EOL, microtime(true) - $t0); 

结果(86 PHP版本):

Running 10,000 iterations on PHP/5.3.28... 
Raw:       1.388s 
@:       1.232s 
Local set_error_handler(): 1.638s 
General set_error_handler(): 1.497s 
Running 10,000 iterations on PHP/5.4.24... 
Raw:       1.170s 
@:       1.185s 
Local set_error_handler(): 1.357s 
General set_error_handler(): 1.326s 
Running 10,000 iterations on PHP/5.5.22... 
Raw:       1.185s 
@:       1.341s 
Local set_error_handler(): 4.960s 
General set_error_handler(): 4.570s 
Running 10,000 iterations on PHP/5.6.10... 
Raw:       1.139s 
@:       1.139s 
Local set_error_handler(): 1.263s 
General set_error_handler(): 1.232s 
Running 10,000 iterations on PHP/7.0.0beta1... 
Raw:       1.232s 
@:       1.279s 
Local set_error_handler(): 1.669s 
General set_error_handler(): 1.669s 
相关问题