2012年7月21日

[PHP]debug_backtrace() で処理を追いかける

便利なのによく忘れるのでメモ。

仕事でどこかの誰かが書いたか分からない、ドキュメントも無い俺俺フレームワークの面倒を見ることが多いのだけど
そういうものの処理を追いかける時に便利!

例えばこんな構造のコードがあったとします。
index.php にアクセスすると 
class A のインスタンスを作成して
class B のstatic hoge を呼び出し
class C のhuga() を実行します。

・index.php
<?php

require_once("./classA.php");
require_once("./classB.php");

// index.php
$a = new A();

・classA.php
<?php
class A
{
    public function A()
    {
        B::hoge();
    }
}

・classB.php
<?php
class B
{
static function hoge()
    {
        print "hoge() called.";
    }
}

・classC.php
<?php
class C
{
public function huga()
{
print "huga() called.";
}
}

この状態でindex.php にアクセスすると

huga() called.

とだけ表示されます。

もっと複雑に絡みあってくると、整備されていないととてもじゃないけど追いかけてられません。

そこで、hoge()メソッド内の
print "hoge() called."; の前に

var_dump(debug_backtrace());

を記述すると
実行結果がこうなります(配列を見やすいように整形してます)

array(3) {
[0]=> array(7) {
["file"]=> string(78) "DocumentRoot\classB.php"
["line"]=> int(7)
["function"]=> string(4) "huga"
["class"]=> string(1) "C"
["object"]=> object(C)#2 (0) { }
["type"]=> string(2) "->"
["args"]=> array(0) { }
}
[1]=> array(6) {
["file"]=> string(78) "DocumentRoot\classA.php"
["line"]=> int(7)
["function"]=> string(4) "hoge"
["class"]=> string(1) "B"
["type"]=> string(2) "::"
["args"]=> array(0) { }
}
[2]=> array(7) {
["file"]=> string(77) "DocumentRoot\index.php"
["line"]=> int(7)
["function"]=> string(1) "A"
["class"]=> string(1) "A"
["object"]=> object(A)#1 (0) { }
["type"]=> string(2) "->"
["args"]=> array(0) { }
}
}
huga() called.

添え字の大きい方から順に処理されていきます。
file => 呼ばれるファイル
line => ファイル内の処理行
function => 呼ばれるメソッド名
class => クラス名
object => 対象のオブジェクト
type => -> が オブジェクトからの呼び出し、 :: はstatic での呼び出し。関数呼び出しは何も表示されない模様
args => 引数


これがあるのを忘れて、ついコードを追いかけてしまいます。
なんていう時間の無駄をしないようにしよう。