Rozważmy następujący kod:
<?
class BtTest
{
public function getTheItem()
{
var_dump(debug_backtrace(false));
$bt = debug_backtrace(false);
return $bt[1];
}
public function __call($methodName, $methodArgs)
{
return $this->getTheItem();
}
}
$o = new BtTest();
$bti = $o->test();
assert('array_key_exists("function", $bti)');
assert('array_key_exists("line", $bti)');
assert('array_key_exists("file", $bti)');
Realizacja powyższego przykładu generuje następujące dane wyjściowe:
array(3) {
[0]=>
array(6) {
["file"]=>
string(53) "/somewhere/in/the/filesystem/tests/bt-test-so.php"
["line"]=>
int(13)
["function"]=>
string(10) "getTheItem"
["class"]=>
string(6) "BtTest"
["type"]=>
string(2) "->"
["args"]=>
array(0) {
}
}
[1]=>
array(4) {
["function"]=>
string(6) "__call"
["class"]=>
string(6) "BtTest"
["type"]=>
string(2) "->"
["args"]=>
array(2) {
[0]=>
&string(4) "test"
[1]=>
&array(0) {
}
}
}
[2]=>
array(6) {
["file"]=>
string(53) "/somewhere/in/the/filesystem/tests/bt-test-so.php"
["line"]=>
int(18)
["function"]=>
string(4) "test"
["class"]=>
string(6) "BtTest"
["type"]=>
string(2) "->"
["args"]=>
array(0) {
}
}
}
PHP Warning: assert(): Assertion "array_key_exists("line", $bti)" failed in /somewhere/in/the/filesystem/tests/bt-test-so.php on line 21
PHP Warning: assert(): Assertion "array_key_exists("file", $bti)" failed in /somewhere/in/the/filesystem/tests/bt-test-so.php on line 22
pierwszej pozycji ślad (indeks 0) mówi pośrednio (poprzez line
i file
przedmiotów), że metoda getTheItem
została wywołana z metody __call
.
Drugi element backtrace (indeks 1) mówi, że metoda __call
nazwano od gdzieś (brak line
i file
pozycji).
Trzeci ślad śledzenia (indeks 2) mówi, że metoda test
została wywołana z globalnego zakresu skryptu.
Miejsce wywołania metody __call
jest prawdopodobnie w pewnym kodzie rozpoznawania metody gdzieś w kodzie interpretatora php. Istnieją dwie możliwości jego naprawy. Druga pozycja powinna odnosić się do pliku kodu źródłowego tłumacza, a druga lub trzecia pozycja śledzenia wstecznego powinny zostać scalone w jeden. Osobiście wolałbym drugie rozwiązanie, ponieważ wewnętrzne ustawienia interpretera nie są dla mnie interesujące (tak wyglądają w śledzeniu Pythona), ale rozumiem, że czasami pierwsze rozwiązanie zapewnia bardziej wyraźny ślad (zwłaszcza gdy jest to wywołanie zwrotne, które jest wywołany z wewnętrznych elementów).
Wygląda na to, że programista (y) odpowiedzialny za (lub przynajmniej utrzymanie) kod funkcji debug_backtrace
nie postrzega go jako błąd lub może nie ma łatwego sposobu na jego naprawienie. Byłoby dobrze wypełnić elementy line
i file
z niektórymi wartościami uchwytów (np. <unknown-file>
i 0
lub nawet nulls) i podkreślić je w dokumentacji. Jeśli ktoś nie przekonuje ich, aby to zrobić, wystarczy zająć się specjalnym przypadkiem w swoim kodzie.
Napisałem powyżej, aby podzielić się moim zrozumieniem dziwnego zachowania funkcji.Jeśli ktoś ma chęć do walki o nieco lepszego świata, oto linki do niektórych powiązanych raportów o błędach:
Najstarszy raport pochodzi z 2003 roku, więc nie powinieneś liczyć na szybką naprawę :)
Interesujące. Czy możesz wysłać przykład? – deceze
Czy jest to być może wewnątrz wyjątku, zamknięcia, kodu evaled, funkcji tick, obsługi błędów (w zasadzie dowolny kod, który działa poza zwykłym stosem wykonania)? Poza tym, nie rozumiem, dlaczego nie otrzymasz numerów linii (przynajmniej bez przykładu) ... – ircmaxell
@deceze - Kod jest zbyt skomplikowany, by opublikować przykład. Chciałbym móc, ale najprawdopodobniej potrwałoby to kilka godzin lub dłużej, aby zidentyfikować coś na tyle prostego, by móc pisać i nie jest to dla mnie zbyt dużym problemem, aby spędzić cały ten czas. – MikeSchinkel