2015-07-13 63 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 
相關問題