PHP スクリプトをどのようにデバッグしますか?[閉まっている]
質問
どうやってデバッグするのですか PHP スクリプト?
エラー報告の使用などの基本的なデバッグについては理解しています。ブレークポイントのデバッグ PHPEclipse も非常に便利です。
とは何ですか 最高 (高速かつ簡単という点で) phpStorm または他の IDE でデバッグする方法はありますか?
解決
試す 日食PDT 先ほど述べたようなデバッグ機能を備えた Eclipse 環境をセットアップします。コードにステップインする機能は、var_dump の古い方法よりもはるかに優れたデバッグ方法であり、さまざまなポイントで出力してフローのどこが間違っているかを確認できます。ただし、他のすべてが失敗し、SSH と vim しかない場合でも、私はまだ var_dump()
/die()
コードが南に向かう場所を見つけます。
他のヒント
Firebug のアドオンである Firephp を使用すると、JavaScript と同じ環境で PHP をデバッグできます。
私も使っています Xデバッグ phpのプロファイリングについては前述しました。
これは私の小さなデバッグ環境です。
error_reporting(-1);
assert_options(ASSERT_ACTIVE, 1);
assert_options(ASSERT_WARNING, 0);
assert_options(ASSERT_BAIL, 0);
assert_options(ASSERT_QUIET_EVAL, 0);
assert_options(ASSERT_CALLBACK, 'assert_callcack');
set_error_handler('error_handler');
set_exception_handler('exception_handler');
register_shutdown_function('shutdown_handler');
function assert_callcack($file, $line, $message) {
throw new Customizable_Exception($message, null, $file, $line);
}
function error_handler($errno, $error, $file, $line, $vars) {
if ($errno === 0 || ($errno & error_reporting()) === 0) {
return;
}
throw new Customizable_Exception($error, $errno, $file, $line);
}
function exception_handler(Exception $e) {
// Do what ever!
echo '<pre>', print_r($e, true), '</pre>';
exit;
}
function shutdown_handler() {
try {
if (null !== $error = error_get_last()) {
throw new Customizable_Exception($error['message'], $error['type'], $error['file'], $error['line']);
}
} catch (Exception $e) {
exception_handler($e);
}
}
class Customizable_Exception extends Exception {
public function __construct($message = null, $code = null, $file = null, $line = null) {
if ($code === null) {
parent::__construct($message);
} else {
parent::__construct($message, $code);
}
if ($file !== null) {
$this->file = $file;
}
if ($line !== null) {
$this->line = $line;
}
}
}
強力なバグハンティングには Xdebug と Notepad++ 用の DBGp プラグインが、軽量なものには FirePHP が使用されます。早くて汚い?これに勝るものはありません デバグ.
Xデバッグ 開発には欠かせないものです。他の拡張機能よりも先にインストールします。あらゆるエラーに関するスタック トレースが得られ、プロファイリングを簡単に有効にすることができます。
データ構造を簡単に確認するには、次を使用します。 var_dump()
. 。使用しないでください print_r()
で囲む必要があるため、 <pre>
また、一度に 1 つの変数のみを出力します。
<?php var_dump(__FILE__, __LINE__, $_REQUEST); ?>
実際のデバッグ環境の場合、私が見つけた最良のものは次のとおりです コモドIDE ただし、$$かかります。
PhpEdは本当に優れています。関数にステップイン/ステップオーバー/ステップアウトすることができます。アドホック コードを実行したり、変数を検査したり、変数を変更したりできます。すごいですね。
1) print_r() を使用します。TextMate には、次のように展開される「pre」のスニペットがあります。
echo "<pre>";
print_r();
echo "</pre>";
2) Xdebug を使用していますが、GUI を Mac で正しく動作させることができません。少なくともスタック トレースの読み取り可能なバージョンを出力します。
私が使用したのは、 ゼンド スタジオ (5.5), 、 一緒に Zend プラットフォーム. 。これにより、適切なデバッグ、ブレークポイント/コードのステップオーバーなどが可能になりますが、代償はかかります。
正直に言うと、変数を出力するには print と print_r() を組み合わせます。他のより高度な方法を使用することを好む人は多いと思いますが、私はこれが最も使いやすいと思います。
言っておきますが、私は大学でマイクロプロセッサのプログラミングをするまで、この機能の良さを十分に理解していませんでしたが、これさえも使用することができませんでした。
Xデバッグ, デリック・レサンズ著、とても良いです。しばらく前に使用しましたが、インストールがそれほど簡単ではないことがわかりました。終わってしまえば、それなしでどうやってやっていたのか理解できなくなるでしょう :-)
良い記事があります Zend 開発者ゾーン (Linux へのインストールはそれほど簡単ではないようです) Firefox プラグイン, 、私は決して使用しませんでした。
XDebug で Netbeans を使用します。構成方法に関するドキュメントについては、Web サイトで確認してください。http://php.netbeans.org/
私は Netbeans を XDebug で使用しています。 Easy XDebug FireFox アドオン
Netbeans で XDebug を実行する通常の方法では、URL を介して dbug セッションを登録するため、MVC プロジェクトをデバッグする場合、アドオンは不可欠です。FireFox にアドオンがインストールされている場合、Netbeans プロジェクトのプロパティを設定し、[構成の実行] -> [詳細設定] を選択し、[Web ブラウザを開かない] を選択します。これで、ブレーク ポイントを設定し、通常どおり Ctrl-F5 でデバッグ セッションを開始できます。 。FireFox を開き、右下隅にあるアドオン アイコンを右クリックして、ブレークポイントの監視を開始します。コードがブレークポイントに到達すると停止し、変数の状態と呼び出しスタックを検査できます。
出力バッファリングは、出力を混乱させたくない場合に非常に便利です。これをワンライナーで行い、自由にコメント/コメント解除できます
ob_start();var_dump(); user_error(ob_get_contents()); ob_get_clean();
PhpEdit にはデバッガが組み込まれていますが、通常は echo(); を使用することになります。そしてprint_r();昔ながらのやり方!!
print_r/echo を使用して解決するには時間がかかりすぎるような、非常に深刻な問題については、IDE (PhpEd) のデバッグ機能を使用します。私が使用した他の IDE とは異なり、PhpEd はセットアップをほとんど必要としません。遭遇した問題に対して私がそれを使用しない唯一の理由は、 痛々しいほどに 遅い。遅さが PhpEd または他の PHP デバッガーに特有のものであるかどうかはわかりません。PhpEd は無料ではありませんが、とにかくオープンソース デバッガ (前述の XDebug など) の 1 つを使用していると思います。繰り返しますが、PhpEd の利点は、これまで非常に面倒だと感じていたセットアップが必要ないことです。
私にとっては、手動デバッグのほうが一般的に早いです - var_dump()
そして debug_print_backtrace()
ロジックを準備するために必要なツールはすべて揃っています。
まあ、それはある程度、物事がどこに進むかによって決まります。これを最初に分離しようとして、必要に応じて echo/print_r() を使用します。
注意:print_r() の 2 番目の引数として true を渡すと、出力を印刷する代わりに返すことができることをご存知ですか?例えば。:
echo "<pre>".print_r($var, true)."</pre>";
Railsが使えない場合はCakePHPを使うことが多いです。エラーをデバッグするには、通常、 error.log
tmp フォルダーに移動し、ターミナルで次のコマンドを実行します...
tail -f app/tmp/logs/error.log
これは、何が起こっているかをケーキから実行するダイアログを提供します。これは、コードの途中で使用できる何かを出力したい場合に非常に便利です。
$this->log('xxxx');
通常、これにより、何が起こっているのか、何が間違っているのかについての良いアイデアが得られます。
print_r( debug_backtrace() );
またはそのようなもの:-)
Komodo IDE は、remore デバッグの場合でも、xdebug とうまく連携します。最小限の構成が必要です。必要なのは、Komodo がブレークポイントでコードをステップ実行するためにローカルで使用できるバージョンの php だけです。スクリプトを komodo プロジェクトにインポートしている場合は、Java プログラムをデバッグするために Eclipse 内でブレークポイントを設定するのと同じように、マウスクリックでブレークポイントを設定できます。リモート デバッグは、MAC または Linux デスクトップを使用している場合は非常に簡単に設定できるローカル デバッグ設定よりも、正しく動作させるのが明らかに難しいです (リモート URL をワークスペース内の PHP スクリプトにマップする必要がある場合があります)。 。
Nusphere は PHP の優れたデバッガーでもありますヌスフィア
コーディング時に膨大な時間を節約できる PHP デバッグ手法が多数あります。効果的だが基本的なデバッグ手法は、単純にエラー報告を有効にすることです。もう 1 つのもう少し高度なテクニックには、print ステートメントの使用が含まれます。これは、実際に何が起こっているかを画面上に表示することで、よりとらえどころのないバグを正確に特定するのに役立ちます。PHPeclipse は、一般的な構文エラーを強調表示できる Eclipse プラグインであり、デバッガーと組み合わせて使用してブレークポイントを設定できます。
display_errors = Off
error_reporting = E_ALL
display_errors = On
そしてまた使用されました
error_log();
console_log();
運用環境では、error_log() を使用して関連データをサーバーのエラー ログに記録します。
私は組み込みデバッガーを備えた Eclipse 用の zend Studio を使用しています。xdebug を使用した Eclipse pdt によるデバッグと比較すると、それでも遅いです。これらの問題が修正されることを願っています。最近のリリースよりも速度は向上していますが、それでもステップオーバーには 2 ~ 3 秒かかります。Zend Firefox ツールバーを使用すると、作業が非常に簡単になります (次のページ、現在のページのデバッグなど)。また、コードのベンチマークを実行し、円グラフや実行時間などを提供するプロファイラーも提供します。
ほとんどのバグは次の方法で簡単に見つけることができます。 var_dump
重要な変数のいくつかを説明しますが、それは開発するアプリケーションの種類によって明らかに異なります。
より複雑なアルゴリズムの場合、ステップ/ブレークポイント/ウォッチ関数は (必要でない場合) 非常に役立ちます。
PHP DBG
インタラクティブ ステップスルー PHP デバッガーは、SAPI モジュールとして実装されており、コードの機能やパフォーマンスに影響を与えることなく、環境を完全に制御できます。これは、軽量で強力で使いやすい PHP 5.4 以降のデバッグ プラットフォームを目指しており、PHP 5.6 とともに出荷されます。
機能には次のものが含まれます。
- ステップスルーデバッグ
- 柔軟なブレークポイント (クラスメソッド、関数、ファイル:行、アドレス、オペコード)
- 組み込みの eval() を使用して PHP に簡単にアクセス
- 現在実行中のコードに簡単にアクセス
- ユーザーランドAPI
- SAPI に依存しない - 簡単に統合
- PHP 構成ファイルのサポート
- JIT スーパー グローバル - 自分で設定しましょう!!
- オプションの readline サポート - 快適な端末操作
- リモート デバッグ サポート - バンドルされた Java GUI
- 簡単操作
スクリーンショットを参照してください。
ホームページ: http://phpdbg.com/
PHPエラー - PHP のエラーレポートの改善
これは、PHP スクリプトをデバッグするために非常に使いやすいライブラリ (実際にはファイル) です。
必要な唯一のことは、次のように 1 つのファイルを (コードの先頭に) 含めることです。
require('php_error.php');
\php_error\reportErrors();
その後、すべてのエラーから、バックトレース、コード コンテキスト、関数の引数、サーバー変数などの情報が得られます。例えば:
特徴は次のとおりです。
- 使い方は簡単、ファイルは 1 つだけです
- 通常および ajaxy リクエストでブラウザに表示されるエラー
- AJAX リクエストは一時停止され、自動的に再実行できます。
- エラーを可能な限り厳密にします (コードの品質が促進され、パフォーマンスが向上する傾向があります)
- スタック トレース全体にわたるコード スニペット
- 詳細情報 (完全な関数シグネチャなど) を提供します。
- 明らかに間違っているいくつかのエラーメッセージを修正します
- 構文の強調表示
- きれいに見えます!
- カスタマイズ
- 手動でオンとオフを切り替えます
- エラー報告なしで特定のセクションを実行する
- ファイルを無視すると、スタック トレース内のコードの強調表示を避けることができます
- アプリケーションファイル。エラーが発生した場合、これらが優先されます。
ホームページ: http://phperror.net/
GitHub: https://github.com/JosephLenton/PHP-Error
私のフォーク(追加の修正を加えたもの): https://github.com/kenorb-contrib/PHP-Error
DTレース
お使いのシステムがサポートしている場合 DTrace 動的トレース (OS X ではデフォルトでインストールされます)、PHP は DTrace プローブを有効にしてコンパイルされます (--enable-dtrace
) これはデフォルトであるはずですが、このコマンドは時間をかけずに PHP スクリプトをデバッグするのに役立ちます。
sudo dtrace -qn 'php*:::function-entry { printf("%Y: PHP function-entry:\t%s%s%s() in %s:%d\n", walltimestamp, copyinstr(arg3), copyinstr(arg4), copyinstr(arg0), basename(copyinstr(arg1)), (int)arg2); }'
したがって、次のエイリアスが追加されたとすると、 ラジコン ファイル (例: ~/.bashrc
, ~/.bash_aliases
):
alias trace-php='sudo dtrace -qn "php*:::function-entry { printf(\"%Y: PHP function-entry:\t%s%s%s() in %s:%d\n\", walltimestamp, copyinstr(arg3), copyinstr(arg4), copyinstr(arg0), basename(copyinstr(arg1)), (int)arg2); }"'
覚えやすいエイリアスを使用してスクリプトをトレースできます。 trace-php
.
これはより高度な dtrace スクリプトです。これを次の場所に保存します。 dtruss-php.d
, 、実行可能にします(chmod +x dtruss-php.d
) そして実行します:
#!/usr/sbin/dtrace -Zs
# See: https://github.com/kenorb/dtruss-lamp/blob/master/dtruss-php.d
#pragma D option quiet
php*:::compile-file-entry
{
printf("%Y: PHP compile-file-entry:\t%s (%s)\n", walltimestamp, basename(copyinstr(arg0)), copyinstr(arg1));
}
php*:::compile-file-return
{
printf("%Y: PHP compile-file-return:\t%s (%s)\n", walltimestamp, basename(copyinstr(arg0)), basename(copyinstr(arg1)));
}
php*:::error
{
printf("%Y: PHP error message:\t%s in %s:%d\n", walltimestamp, copyinstr(arg0), basename(copyinstr(arg1)), (int)arg2);
}
php*:::exception-caught
{
printf("%Y: PHP exception-caught:\t%s\n", walltimestamp, copyinstr(arg0));
}
php*:::exception-thrown
{
printf("%Y: PHP exception-thrown:\t%s\n", walltimestamp, copyinstr(arg0));
}
php*:::execute-entry
{
printf("%Y: PHP execute-entry:\t%s:%d\n", walltimestamp, basename(copyinstr(arg0)), (int)arg1);
}
php*:::execute-return
{
printf("%Y: PHP execute-return:\t%s:%d\n", walltimestamp, basename(copyinstr(arg0)), (int)arg1);
}
php*:::function-entry
{
printf("%Y: PHP function-entry:\t%s%s%s() in %s:%d\n", walltimestamp, copyinstr(arg3), copyinstr(arg4), copyinstr(arg0), basename(copyinstr(arg1)), (int)arg2);
}
php*:::function-return
{
printf("%Y: PHP function-return:\t%s%s%s() in %s:%d\n", walltimestamp, copyinstr(arg3), copyinstr(arg4), copyinstr(arg0), basename(copyinstr(arg1)), (int)arg2);
}
php*:::request-shutdown
{
printf("%Y: PHP request-shutdown:\t%s at %s via %s\n", walltimestamp, basename(copyinstr(arg0)), copyinstr(arg1), copyinstr(arg2));
}
php*:::request-startup
{
printf("%Y, PHP request-startup:\t%s at %s via %s\n", walltimestamp, basename(copyinstr(arg0)), copyinstr(arg1), copyinstr(arg2));
}
ホームページ: dtruss ランプ GitHub で
簡単な使用法は次のとおりです。
- 走る:
sudo dtruss-php.d
. - 別の端末で次を実行します。
php -r "phpinfo();"
.
それをテストするには、任意の docroot にアクセスしてください。 index.php
そして、次のようにして PHP 組み込みサーバーを実行します。
php -S localhost:8080
その後、次の場所からサイトにアクセスできます。 http://ローカルホスト:8080/ (または都合の良いポートを選択してください)。そこからいくつかのページにアクセスして、トレース出力を確認します。
注記:Dtrace は OS X ではデフォルトで利用可能ですが、Linux ではおそらく必要になります dtrace4linux または他のものを確認してください 代替案.
見る: PHP と DTrace の使用 php.netで
システムタップ
あるいは、SystemTap SDT 開発パッケージ (例: yum install systemtap-sdt-devel
).
これがスクリプトの例です (all_probes.stp
) SystemTap を使用して PHP スクリプトを実行している間、すべてのコア PHP 静的プローブ ポイントをトレースします。
probe process("sapi/cli/php").provider("php").mark("compile__file__entry") {
printf("Probe compile__file__entry\n");
printf(" compile_file %s\n", user_string($arg1));
printf(" compile_file_translated %s\n", user_string($arg2));
}
probe process("sapi/cli/php").provider("php").mark("compile__file__return") {
printf("Probe compile__file__return\n");
printf(" compile_file %s\n", user_string($arg1));
printf(" compile_file_translated %s\n", user_string($arg2));
}
probe process("sapi/cli/php").provider("php").mark("error") {
printf("Probe error\n");
printf(" errormsg %s\n", user_string($arg1));
printf(" request_file %s\n", user_string($arg2));
printf(" lineno %d\n", $arg3);
}
probe process("sapi/cli/php").provider("php").mark("exception__caught") {
printf("Probe exception__caught\n");
printf(" classname %s\n", user_string($arg1));
}
probe process("sapi/cli/php").provider("php").mark("exception__thrown") {
printf("Probe exception__thrown\n");
printf(" classname %s\n", user_string($arg1));
}
probe process("sapi/cli/php").provider("php").mark("execute__entry") {
printf("Probe execute__entry\n");
printf(" request_file %s\n", user_string($arg1));
printf(" lineno %d\n", $arg2);
}
probe process("sapi/cli/php").provider("php").mark("execute__return") {
printf("Probe execute__return\n");
printf(" request_file %s\n", user_string($arg1));
printf(" lineno %d\n", $arg2);
}
probe process("sapi/cli/php").provider("php").mark("function__entry") {
printf("Probe function__entry\n");
printf(" function_name %s\n", user_string($arg1));
printf(" request_file %s\n", user_string($arg2));
printf(" lineno %d\n", $arg3);
printf(" classname %s\n", user_string($arg4));
printf(" scope %s\n", user_string($arg5));
}
probe process("sapi/cli/php").provider("php").mark("function__return") {
printf("Probe function__return: %s\n", user_string($arg1));
printf(" function_name %s\n", user_string($arg1));
printf(" request_file %s\n", user_string($arg2));
printf(" lineno %d\n", $arg3);
printf(" classname %s\n", user_string($arg4));
printf(" scope %s\n", user_string($arg5));
}
probe process("sapi/cli/php").provider("php").mark("request__shutdown") {
printf("Probe request__shutdown\n");
printf(" file %s\n", user_string($arg1));
printf(" request_uri %s\n", user_string($arg2));
printf(" request_method %s\n", user_string($arg3));
}
probe process("sapi/cli/php").provider("php").mark("request__startup") {
printf("Probe request__startup\n");
printf(" file %s\n", user_string($arg1));
printf(" request_uri %s\n", user_string($arg2));
printf(" request_method %s\n", user_string($arg3));
}
使用法:
stap -c 'sapi/cli/php test.php' all_probes.stp
見る: PHP DTrace 静的プローブでの SystemTap の使用 php.netで
print_r() の場合は +1。これを使用して、オブジェクトまたは変数の内容をダンプします。読みやすくするには、pre タグを使用して、ソースを表示する必要がないようにします。
echo '<pre>';
print_r($arrayOrObject);
また、var_dump($thing) - これは、subthing のタイプを確認するのに非常に便利です
問題に応じて、私は error_reporting(E_ALL) とエコー テストを組み合わせるのが好きです (最初にエラーが発生した問題の行/ファイルを見つけるため)。必ずしも php が指示する行/ファイルではないことはご存知ですか?)、IDE の中かっこ一致 (「解析エラー: を解決するため」)構文エラー、予期しない $end" の問題)、および print_r();出口;ダンプ (本物のプログラマはソースを表示します ;p)。
また、「memory_get_usage();」でphpdebug(sourceforgeをチェック)に勝ることはできません。および "memory_get_peak_usage();"問題領域を見つけるため。
コードをステップ実行するときに変数の値の変化を観察できる統合デバッガーは、非常に優れています。ただし、サーバー上でソフトウェアをセットアップし、クライアント上である程度の構成を行う必要があります。どちらも良好な状態を維持するには定期的なメンテナンスが必要です。
print_r は記述が簡単で、どのような設定でも動作することが保証されています。
通常、ファイルに保存し、デバッグ情報を保存し、最終的に共通のフッターに再出力できるカスタム ログ関数を作成します。
共通の Exception クラスをオーバーライドして、このタイプのデバッグを半自動化することもできます。