Laravel4、スタックトレースの位置をNetBeansで開く

タグ: Laravel4   PHP  

注意:この記事は内容が古くなってしまい、動作しません。新しい記事をご覧ください。

追記:この記事はベータ4の時点で書いています。記事を書いて一週間後に例外ハンドリングにWhoopsというプロジェクトが取り込まれました。画面左にスタックトレース、右側に例外発生時の状況とスタックされた呼び出しライン周辺のコードが表示されます。スタックトレースをクリックすると、その周辺のコードが表示される仕組みです。これはxDebugのfile_link_formatに対応していません。そのため、記事を修正しました。

私はNetBeans使いです。Laravel4でエラー時に原因を探るため、スタックトレースをおいかけるとき、面倒なのでファイル名をリンクしたら、そのファイルのコードを表示するように改造しようかなと思い、エラー表示の部分のコードを眺めていました。

そうしたら"xdebug.file_link_format"という文字が目に入りました。ファイルリンクの機能を生かしたままにしてくれているようです。

それならば、話は簡単です。改造をしないで、スタックトレースのリンクをクリックしたら、対応するファイルの行番号でNetBeansを開くようにしました。

なお、下で紹介する方法はLinuxの場合です。MACやWindowsの場合とは異なります。ですが「こうしたことができる」と分かっているのであれば、調べるのは比較的簡単でしょう。

概要

xDebugはエラー時に表示されるスタックトレースに指定した形式でリンクを張る機能を持っています。(追記:Whoops採用に伴う変更のため、今回の修正はxdebugの機能とは関係なくなりました。)

またブラウザは特定のプロトコルに対して、指定されたプログラムを用いて開く機能を持っています。

エディターやIDEは通常、コマンドラインで起動する場合、開くファイルと何行目にカーソルを移動するのかを表示する指定が可能です。

これらを組み合わせ、スタックトレース中の行をクリックすれば、IDEやエディターを開き、該当ファイの該当行が表示されるように設定します。

プロトコル名

今回私はNetBeansでコードを開くための独自プロトコル名として"netbeans"を使用しました。この名前は既存の文字列、つまりプロトコル名でなければ問題になりません。お好きなものを選べます。

シェルスクリプト

まずシェルスクリプトを作成します。今回紹介する方法がどんなエディター・IDEにも対応できるので、一番簡単です。NetBeansに限らず、他のエディターやIDEでも起動できます。ご使用のエディターやIDEでコマンドライン起動の時に、どのオプションを使用し、どんな形式でファイルと行番号を指定してファイルを開くのかを調べてください。

/ユーザー名/binの中に"netbeans"ファイルを作成してください。(もちろん名前はお好きなもので結構です。)

#!/bin/bash

f=`echo $1 | cut -d @ -f 1 | sed 's/netbeans:\/\///'`
l=`echo $1 | cut -d @ -f 2`

/home/hiro/netbeans-7.3/bin/netbeans --open $f:$l

上記では現在の私の状態に合わせてNetBeansへのパスを指定していますが、実際は皆さんの環境のNetBeans実行形式へのフルパスを指定してください。もちろん、他のプログラムを起動するのであれば、それに合わせてください。(引数の渡し方も、起動するプログラムに合わせましょう。$fがファイル名、$lが行番号です。)

sed…の後に続く、'netbeans'はプロトコル名です。皆さんが設定したプロトコル名にしましょう。(NetBeansを使用しない場合であっても、面倒ならnetbeansのままでも大丈夫です。最後の起動コマンドラインのみ修正してください。)

firefoxの設定

Linux上のFirefoxで、特定のプロトコルを開く設定方法です。

  1. 上部のロケーションバーにabout:configと入力し、Enterを叩いてください。警告ダイアログがでますが、OKボタンをクリックし、進めてください。
  2. 設定名と値の一覧が表示されます。どこでも良いので右クリックし、メニューの中から「新規作成」、「真偽値」を選びます。
  3. 設定名に"network.protocol-handler.expose.netbeans"と入力し、値は"false"を選択します。最後の"netbeans"がプロトコル名です。別のプロトコル名を使用する場合はここを変更してください。

この時点では、プロトコルに起動するプログラムは結び付けられていません。上記の例であれば"netbeans"プロトコルのリンクをクリックした時に初めて、起動するプログラムを指定するようにFirefoxから催促されます。手順の最後で説明します。

php.intの変更

php.ini、最近は設定ファイルは各機能でバラされていることが多いようですので、/etc/php5/conf.d/xdebug.iniなどかもしれませんが、次の行を追加します。(ディレクトリー名はディストリビューションにより異なります。)

xdebug.file_link_format = "netbeans://%f@%l"

これでスタックトレースのファイル名には上記で指定した形式のリンクが付きます。例えば/home/user/a.phpの10行目であれば、"netbeans://home/user/a.php@10"というリンクが貼られます。

php.ini関連の変更を行った場合は、apacheの再起動を忘れずに行いましょう。

プロトコルに対するプログラム指定

NetBeansを起動し、Laravel4上で動作する、実行時エラーになるコードを書いてください。それを実行しましょう。

スタックトレースが表示されたら、カーソルを合わせてみればリンクが張られているのを確認できます。

それをクリックしてください。どのプログラムで起動するか尋ねられます。先ほど作成したシェルスクリプトを指定してください。

NetBeans上に、そのスタックトレースでクリックしたファイルが表示され、行番号の位置にカーソルが移動されているはずです。

これで、エラー時の対応も楽になりますね。

追記:Whoopsテンプレートの修正

Whoopsが取り込まれたため、一部ファイルを修正する必要が起きました。

Whoopsは表示ページを簡単に変更できるようにPHPファイルをテンプレートとして使用しています。

Laravelはそれをコピーしたものをプロジェクトに持っています。当然表示するときには、Laravelプロジェクトのテンプレートを利用し表示します。これを変更し、独自プロトコルによるリンクを張るように修正しましょう。

変更するテンプレートはvendor/laravel/framework/src/Illuminate/Exception/resources/pretty-template.phpです。同名のファイルがvendor/filp/whoops/src/Whoops/Resources/pretty-template.phpにも存在しますが、そちらはオリジナルのファイルです。ですから修正しても表示内容は変更されません。(これで数時間はまりました)

修正箇所は現在のところ69行目ですが、変更されるかも知れません。

修正前:

<div class="frame-file">
  <strong><?php echo $e($frame->getFile() ?: '<#unknown>') ?></strong>
</div>

修正後:

<div class="frame-file">
    <strong><?php echo '<a href="netbeans://'.$frame->getFile().
                     '@'.$frame->getLine().'">'.
                     $frame->getFile().'</a>' ? : '<#unknown>' ?>
    </strong>
</div>

ご覧のように、独自プロトコル、この場合は"netbeans"に対し、リンクを張るようにハードコードしています。

本来は、xDebugのfile_link_formatが指定されているかチェックし、指定されているならば指定されたフォーマットでリンクを張るのが正しいやり方です。奏してもらえるよう、Laravelのgithubに要望は出しておきます。