2009-08-09 10 views
41

Wyobraźmy mam następującą sytuację:Uzyskaj linię kodu i plik, który uruchamia bieżącą funkcję w PHP?

File1.php

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

Function.php

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

Chcę zmienić funkcję dziennika tak, że będzie produkować co następuje:

test (plik: File1.php, numer linii: 3)

W jaki sposób uzyskać nazwę pliku i numer wiersza kodu, który wykonywał bieżącą funkcję w PHP?

EDIT komentarze użytkowania zaległości: Gdy używam zaległości w moim Object Oriented sposobem programowania mam następującą sytuację.

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']; 
    } 
} 
?> 

Przykład powróci w pliku "index.php" i jako numer linii 4, jest to miejsce, w którym klasa jest inicjowana. Jednak ma on zwrócić plik TestClass.class.php i numer linii 6. Dowolny pomysł, jak to naprawić?

Odpowiedz

73

Możesz użyć debug_backtrace().

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

Więc w funkcji logarytmicznej, byłbyś w stanie odzyskać nazwę pliku i numer linii, z której funkcja log został powołany.

Używam tego podejścia w moich klasach rejestrowania i znacznie zmniejszyło to ilość kodu wymaganą do uzyskania znaczących danych dziennika. Inną korzyścią byłaby czytelność. Magiczne stałe mają tendencję do bycia dość brzydkimi, gdy są mieszane ze strunami.

Oto krótki przykład:

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

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

    // do your logging stuff here.  
} 
+1

W rzeczywistości jest problem. Koduję w sposób zorientowany obiektowo i zwracam linię oraz skrypt wywołujący obiekt, w którym wywoływana jest funkcja. Zamiast tego powinien podać nazwę dołączonej klasy i linii w tym pliku klasy. Dowolny pomysł? – Tom

+0

Musisz być dokładniejszy tutaj. Czy możesz pokazać mi, co otrzymujesz i czego oczekujesz? –

+0

Witaj Lior Cohen, czy możesz sprawdzić mój zredagowany oryginalny post? Dokładnie to wyjaśniłem. Dzięki! – Tom

21

debug_backtrace() może być użyty do śledzenia wstecz stosu wywołań. Może to być powolne, więc należy zachować ostrożność, jeśli robisz dużo logowania.

Jeśli używasz PHP 5.3, można skorzystać z late static binding i posiadają metodę klasy bazowej log(), a twoje zajęcia dziecko może to nazwać, ale nadal utrzymują referencje statycznych __FILE__ i __LINE__.

Ostatnią opcją byłoby po prostu przekazanie __FILE__ i __LINE__ jako parametrów podczas wywoływania funkcji log().

+0

'__FILE__' i' __LINE__' mogą być o wiele wydajniejsze, chociaż dodają bałagan kodu. Przy okazji, może właściwe debugowanie może zastąpić rejestrowanie plików/linii, gdy zajdzie taka potrzeba. – christopheml

+0

'debug_backtrace()' powolne w 2 razy z '__LINE__', ale to pozwala na 100 wywołań w 1 ms dla przeciętnego komputera lub 1000 wywołań w 1 ms dla serwera o dużej mocy. Więc nie jest tak wolno, jak być może. – Enyby

1

Jest to stary pytanie, ale skoro, jak moje rozwiązanie nie jest tutaj, będę dostarczyć go dla potomności

 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))); 

Można rzucać/catch aby uzyskać czysty ślad stosu, musisz poszukać pierwszej linii, która zawiera ten plik (zwykle tam, skąd jest wywoływany), możesz również użyć indeksu śledzenia, jeśli go znasz, lub funkcji.

Ślad stosu wyjątków jest prawie taki sam jak wykonanie debug_backtrace(true).

Powiązane problemy