2012-07-20 57 views
4

在file1.php:ErrorException返回錯誤的文件和行

set_error_handler('my_error_handler'); 
set_exception_handler('my_exception_handler'); 

function my_error_handler($errNo, $errStr, $errFile, $errLine, $whatever = null){ 
    // here ErrFile and $errLine are correct only for native funcs... 
    throw New ErrorException($errStr, 0, $errNo, $errFile, $errLine); 
} 

function my_exception_handler($exception){ 
    print $exception->getLine(); // correct only for native functions 
    print $exception->getFile(); // correct only for native functions 
} 

在file2.php,一個例子函數定義:

function foo($requiredArg){ 

} 

和file3.php,調用foo:

foo(); 

產生:

foo的(),稱爲file3.php第2行和定義 缺少的參數1 ...

的訊息話題是正確的,但是當我試圖讓該文件並符合$exception->getFile()$exception->getLine()(在我的異常處理程序中),我得到了定義foo()的文件和行,而不是它被調用的地方...

但是使用本地PHP函數,我得到了函數被調用的文件和行是我想要的)。

+2

當你的錯誤處理程序被調用時,你能否確認你得到了正確的文件名和行號? – nickb 2012-07-20 17:01:27

+0

不,我得到相同的文件和行:(這是否意味着PHP將錯誤的參數傳遞給我的錯誤處理程序? – Alex 2012-07-20 17:02:39

回答

1

好問題!

對於本機vs用戶定義的函數,事情似乎有不同的表現。然而,一件顯而易見的事情,如果它是本地的,因爲它是用C編寫的,而不是PHP,所以不能真正告訴你函數的定義在哪裏。在用戶空間代碼的情況下,找到它被稱爲的位置會很好。一種方法是從捕獲的異常中解析錯誤消息,您可以獲取創建它的文件和行。從問題

function my_exception_handler($exception) 
{ 
    $message = $exception->getMessage(); 
    $file = $exception->getFile(); 
    $line = $exception->getLine(); 

    if(strpos($message, 'called in') !== false) { 
     preg_match('/called in .*php/', $message, $matches); 
     $file = str_replace('called in ', '', $matches[0]); 

     preg_match('/on line \d/', $message, $matches); 
     $line = str_replace('on line ', '', $matches[0]); 
    } 

    echo 'line: ' . $line . PHP_EOL; 
    echo 'file: ' . $file . PHP_EOL; 
} 

輸出基於描述與改變my_exception_handler

line: 4 
file: /tmp/file3.php 
2

它簡單地歸結爲最接近第一。

當您使用核心或內置函數時,它們的定義包含在PHP的核心內。這意味着與用戶定義的函數相比,該函數的定義不可用,其定義很容易獲得。

如果你運行一個debug_backtrace();$exception->getTrace();exception_handler功能,引用您的用戶定義的函數的錯誤裏面,你會看到函數的定義第一和第二函數的調用。如果你調用一個內部函數,你將只能看到調用行,因爲PHP不能告訴你腳本中的代碼行或包含的文件中定義了內部函數,因爲它是在內核中定義的。

這是錯誤處理操作的順序。如果你想獲得調用該函數的實際行,可以查看跟蹤並獲取第二個數組對行號的引用。