PHP呼び出しスタックを出力


回答:


123

バックトレースを生成したい場合は、debug_backtraceおよび/またはを探していますdebug_print_backtrace


たとえば、最初のものは、このような配列を取得します(マニュアルを引用)

array(2) {
[0]=>
array(4) {
    ["file"] => string(10) "/tmp/a.php"
    ["line"] => int(10)
    ["function"] => string(6) "a_test"
    ["args"]=>
    array(1) {
      [0] => &string(6) "friend"
    }
}
[1]=>
array(4) {
    ["file"] => string(10) "/tmp/b.php"
    ["line"] => int(2)
    ["args"] =>
    array(1) {
      [0] => string(10) "/tmp/a.php"
    }
    ["function"] => string(12) "include_once"
  }
}


それらは明らかにI / Oバッファをフラッシュしませんが、flushおよび/またはを使用して自分で行うことができますob_flush

(「および/または」の理由については、最初のマニュアルページを参照してください;-))


7
これにより、phpのメモリが不足します。トビアスのソリューションをお勧めします。
ピーディー、2015

読みにくい/理解しにくいと感じた場合は、トビアスのソリューションもお勧めします
ViliusL 2018

1
@peedeeに必要なのは、オプションDEBUG_BACKTRACE_IGNORE_ARGSパラメータの1つを提供することだけです。これにより、機能的に同等になります(new \Exception())->getTraceAsString()

566

より読みやすいdebug_backtrace()

$e = new \Exception;
var_dump($e->getTraceAsString());

#2 /usr/share/php/PHPUnit/Framework/TestCase.php(626): SeriesHelperTest->setUp()
#3 /usr/share/php/PHPUnit/Framework/TestResult.php(666): PHPUnit_Framework_TestCase->runBare()
#4 /usr/share/php/PHPUnit/Framework/TestCase.php(576): PHPUnit_Framework_TestResult->run(Object(SeriesHelperTest))
#5 /usr/share/php/PHPUnit/Framework/TestSuite.php(757): PHPUnit_Framework_TestCase->run(Object(PHPUnit_Framework_TestResult))
#6 /usr/share/php/PHPUnit/Framework/TestSuite.php(733): PHPUnit_Framework_TestSuite->runTest(Object(SeriesHelperTest), Object(PHPUnit_Framework_TestResult))
#7 /usr/share/php/PHPUnit/TextUI/TestRunner.php(305): PHPUnit_Framework_TestSuite->run(Object(PHPUnit_Framework_TestResult), false, Array, Array, false)
#8 /usr/share/php/PHPUnit/TextUI/Command.php(188): PHPUnit_TextUI_TestRunner->doRun(Object(PHPUnit_Framework_TestSuite), Array)
#9 /usr/share/php/PHPUnit/TextUI/Command.php(129): PHPUnit_TextUI_Command->run(Array, true)
#10 /usr/bin/phpunit(53): PHPUnit_TextUI_Command::main()
#11 {main}"

50
くそー、これはずっと良いです、なぜこれをdebug_print_backtrace()のデフォルト出力にできないのですか?エコーしないで変数に入れたい人のためにブールパラメータ「returnTrace」を追加することができ、それは完璧だったでしょう!
jurchiks 2013年

1
それがうまくいくとは決して思っていなかった方法を理解するために何ヶ月も努力してきました
WojonsTech 2013年

このソリューションは、debug_backtrace()の出力を配列としてキャプチャしてから、print_r()を使用して出力するよりもメモリの消費量が少ないようです。
ピーター

5
debug_backtraceスタックトレースの最初のレベルのみを返すように制限する方法を探していました-この解決策でうまくいきます。ありがとうございました!
ankr 2014年

3
@Andrew print_rはすべてのメッセージを保持します。
mopo922 2016年

41

トレースを記録するには

$e = new Exception;
error_log(var_export($e->getTraceAsString(), true));

ありがとう@Tobiasz


35

バックトレースは、不要な大量のゴミをダンプします。時間がかかり、読みにくい。あなたがいつも欲しがっているのは、「何をどこから何と呼ぶか​​」だけです。これは、単純な静的関数ソリューションです。私は通常、それを 'debug'と呼ばれるクラスに入れます。これには、すべてのデバッグユーティリティ関数が含まれています。

class debugUtils {
    public static function callStack($stacktrace) {
        print str_repeat("=", 50) ."\n";
        $i = 1;
        foreach($stacktrace as $node) {
            print "$i. ".basename($node['file']) .":" .$node['function'] ."(" .$node['line'].")\n";
            $i++;
        }
    } 
}

次のように呼び出します。

debugUtils::callStack(debug_backtrace());

そしてそれはこのような出力を生成します:

==================================================
 1. DatabaseDriver.php::getSequenceTable(169)
 2. ClassMetadataFactory.php::loadMetadataForClass(284)
 3. ClassMetadataFactory.php::loadMetadata(177)
 4. ClassMetadataFactory.php::getMetadataFor(124)
 5. Import.php::getAllMetadata(188)
 6. Command.php::execute(187)
 7. Application.php::run(194)
 8. Application.php::doRun(118)
 9. doctrine.php::run(99)
 10. doctrine::include(4)
==================================================


33

誰もがこのように投稿したのは奇妙です:

debug_print_backtrace(DEBUG_BACKTRACE_IGNORE_ARGS);

これは、実際にはガベージなしでバックトレースを出力します-呼び出されたメソッドと場所だけです。


2
確かに、本当に投票されたメインのソリューションと同等で、より短いです。ありがとう
Brunetton 2016

9

phpが例外スタックトレースをフォーマットする方法と非常によく似たスタックトレースが必要な場合は、この関数を使用するのではなく、次のように記述します。

function debug_backtrace_string() {
    $stack = '';
    $i = 1;
    $trace = debug_backtrace();
    unset($trace[0]); //Remove call to this function from stack trace
    foreach($trace as $node) {
        $stack .= "#$i ".$node['file'] ."(" .$node['line']."): "; 
        if(isset($node['class'])) {
            $stack .= $node['class'] . "->"; 
        }
        $stack .= $node['function'] . "()" . PHP_EOL;
        $i++;
    }
    return $stack;
} 

これにより、次のような形式のスタックトレースが返されます。

#1 C:\Inetpub\sitename.com\modules\sponsors\class.php(306): filePathCombine()
#2 C:\Inetpub\sitename.com\modules\sponsors\class.php(294): Process->_deleteImageFile()
#3 C:\Inetpub\sitename.com\VPanel\modules\sponsors\class.php(70): Process->_deleteImage()
#4 C:\Inetpub\sitename.com\modules\sponsors\process.php(24): Process->_delete() 

2
またはただ$e = new Exception; echo $e->getTraceAsString();
ブラッドケント

ブラッド、そのソリューションではスタックトレースから最後の項目が削除されないため、新しい例外が原因のトレース項目は表示されません
TroySteven



4

phptraceは、拡張機能をインストールせずにいつでもPHPスタックを印刷できる優れたツールです。

phptraceには2つの主要な機能があります。1つ目は、何もインストールする必要のないPHPのコールスタックを出力すること、2つ目は、提供する拡張機能をインストールする必要があるphp実行フローをトレースすることです。

次のように:

$ ./phptrace -p 3130 -s             # phptrace -p <PID> -s
phptrace 0.2.0 release candidate, published by infra webcore team
process id = 3130
script_filename = /home/xxx/opt/nginx/webapp/block.php
[0x7f27b9a99dc8]  sleep /home/xxx/opt/nginx/webapp/block.php:6
[0x7f27b9a99d08]  say /home/xxx/opt/nginx/webapp/block.php:3
[0x7f27b9a99c50]  run /home/xxx/opt/nginx/webapp/block.php:10 

Windowsバージョンはありますか?
ジョニー2016年

ここにメモリアドレスが表示されているのが好きです。これは役に立ちます
タイラーマイル

3

debug_backtrace呼び出された関数とメソッド、および呼び出されたポイントにつながったインクルードされたファイルのバックトレースを取得するために使用しますdebug_backtrace





1

Walltearerのソリューションは、特に「pre」タグで囲まれている場合は優れています。

<pre>
<?php debug_print_backtrace(DEBUG_BACKTRACE_IGNORE_ARGS); ?>
</pre>

-別の行に電話をかけ、きちんと番号を付けます


0

私は適応している上にドン・ブリッグスの答えをライブサーバー上で作業するときあなたの大きな関心事であってもよい公共の印刷、のではなく、内部エラー・ログを使用します。また、基本名の代わりに完全なファイルパスを含めるオプションなど、いくつかの変更を追加しました(異なるパスに同じ名前のファイルが存在する可能性があるため)。また、(それを必要とする人のために)完全なノードスタック出力:

class debugUtils {
    public static function callStack($stacktrace) {
        error_log(str_repeat("=", 100));
        $i = 1;
        foreach($stacktrace as $node) {
            // uncomment next line to debug entire node stack
            // error_log(print_r($node, true));
            error_log( $i . '.' . ' file: ' .$node['file'] . ' | ' . 'function: ' . $node['function'] . '(' . ' line: ' . $node['line'] . ')' );
            $i++;
        }
        error_log(str_repeat("=", 100));
    } 
}

// call debug stack
debugUtils::callStack(debug_backtrace());
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.