2009-08-09 81 views
41

想象我有以下情況:獲取在PHP中執行當前函數的代碼行和文件?

File1.php

<?php 
include("Function.php"); 
log("test"); 
?> 

Function.php

<?php 
function log($msg) 
{ 
    echo ""; 
} 
?> 

我想更改日誌功能,因此,它會產生如下:

測試(文件:File1.php,行號:3)

那麼,有什麼方法可以獲取在PHP中執行當前函數的代碼的文件名和行號?

編輯積壓使用評論: 當我使用我的面向對象的編程方式積壓我有以下情況。

的index.php

<?php 
include("Logger.static.php"); 
include("TestClass.class.php"); 
new TestClass(); 
?> 

TestClass.class.php

<?php 
class TestClass 
{ 
    function __construct() 
    { 
    Logger::log("this is a test log message"); 
    } 
} 
?> 

Logger.static.php

<?php 
class Logger 
{ 
    static public function log($msg) 
    { 
    $bt = debug_backtrace(); 
    $caller = array_shift($bt); 
    echo $caller['file']; 
    echo $caller['line']; 
    } 
} 
?> 

這個例子將返回爲文件 「的index.php」 和作爲4號線,這是課程開始的地方。但是,它應該返回文件TestClass.class.php和行號6.任何想法如何解決這個問題?

回答

73

您可以使用debug_backtrace()。

http://us3.php.net/manual/en/function.debug-backtrace.php

所以,在你的日誌功能,您將能夠檢索該日誌函數被調用的文件名和行號。

我在我的日誌記錄類中使用了這種方法,它顯着減少了獲取有意義的日誌數據所需的代碼量。另一個好處是可讀性。與字符串混合時,魔術常數會變得相當難看。

這裏有一個簡單的例子:

function log($msg) 
{ 
    $bt = debug_backtrace(); 
    $caller = array_shift($bt); 

    // echo $caller['file']; 
    // echo $caller['line']; 

    // do your logging stuff here.  
} 
+1

其實,有一個問題。我以面向對象的方式進行編碼,並且它正在返回行和調用調用該函數的對象的腳本。相反,它應該給我包含的類的名稱和該類文件中的行。任何想法? – Tom 2009-08-09 23:53:11

+0

你需要在這裏更具體。你能告訴我你得到了什麼以及你的期望嗎? – 2009-08-10 07:32:55

+0

你好Lior Cohen,你能查看我編輯過的原文嗎?我在那裏詳細解釋了一切。謝謝! – Tom 2009-08-11 10:49:35

21

debug_backtrace()可用於追溯通過調用堆棧。它可能會很慢,所以如果你做了大量的日誌記錄,請小心。

如果你使用PHP 5.3,你可以利用late static binding並有log()一個基類的方法,你的子類可以稱之爲但仍保持靜態引用到__FILE____LINE__

當您調用log()函數時,最後一個選項將僅作爲參數傳入__FILE____LINE__

+0

'__FILE__'和'__LINE__'可能的方式更有效,但它增加了代碼的混亂。順便說一句,也許正確的調試可以在需要時替換文件/行日誌。 – christopheml 2009-08-11 10:52:38

+0

'debug_backtrace()'從'__LINE__'緩慢2次,但是這允許平均計算機在1 ms內完成100個呼叫,在強大的服務器上在1 ms內完成1000個呼叫。所以它可能並不那麼慢。 – Enyby 2014-12-22 08:35:41

1

這是一個老問題,但看到我的解決方案是如何不在這裏,我會爲後人

 try{ 
     throw new Exception(); 
    }catch (Exception $e){ 
     $trace = $e->getTrace(); 
    } 

    $length = 0; 

    foreach ($trace as $t){ 
     if($t['file'] != __FILE__){ 
      break; 
     } 
     ++$length; 
    } 
    return array_slice($trace, ($length - count($trace))); 

你可以拋出/捕獲它提供要獲得乾淨的堆棧跟蹤,那麼您需要查找包含此文件的第一行(通常是從中調用它的位置),如果您知道該文件或函數,還可以使用跟蹤的索引。

的異常堆棧跟蹤幾乎是一樣的做debug_backtrace(true)

相關問題