こんにちは、かつコーチです。
前回は、PHPのバージョンアップで起きやすい非互換エラーとその対処法を解説しました。
今回は少し話題を変えて、「デバッグ」について取り上げます。
コードが思った通りに動かないとき、皆さんはどうやって原因を探していますか。
いきなりXdebugのような便利なツールに手を出すのもいいですが、実はPHPにはvar_dumpやprint_rという、手軽で強力な標準関数が用意されています。
今回はこの2つの使い分けから、一歩進んだツールであるXdebugの導入まで、順を追って解説していきます。
デバッグとは?なぜ必要なのか
デバッグの基本的な考え方
デバッグとは、プログラムの中に潜む不具合(バグ)を見つけて修正する作業のことです。
初心者のうちは「なんとなくコードを書き換えて、動くまで試す」というやり方になりがちです。
しかし、それでは時間がかかるうえに、なぜ直ったのかが分からないまま終わってしまいます。
大事なのは、「今、変数の中に何が入っているのか」を正確に把握することです。
これができれば、エラーの原因を推測ではなく事実で特定できるようになります。
変数の中身が見えないと何が困るのか
私が駆け出しの頃、こんな経験をしました。
フォームから受け取った値を配列に入れて処理していたのですが、なぜか一部のデータだけ表示されません。
コードを何度読み返しても、ロジックはあっているように見えます。
結局、原因は配列のキー名を"user_name"と"username"で書き間違えていた、という単純なタイプミスでした。
このとき、配列の中身をそのまま画面に出力していれば、キー名の違いに一瞬で気づけたはずです。
「頭の中で想像する」のではなく、「実際の中身を目で見る」ことがデバッグの第一歩だと痛感した出来事でした。
var_dumpとprint_rの基本の使い方
var_dumpで型まで確認する
var_dumpは、変数の値と型を両方表示してくれる関数です。
<?php
$name = "かつコーチ";
$age = "20"; // 意図的に文字列にしている
$isActive = true;
var_dump($name);
var_dump($age);
var_dump($isActive);
出力結果は次のようになります。
string(15) "かつコーチ"
string(2) "20"
bool(true)
string(2) "20"のように、値だけでなく型(この場合は文字列)と文字数まで分かるのがポイントです。
「数値のつもりで書いたのに、実は文字列のままだった」というバグは、var_dumpを使えばすぐに発見できます。
print_rで配列を見やすく確認する
一方print_rは、配列やオブジェクトの構造を人間が読みやすい形で表示してくれます。
<?php
$user = [
"name" => "かつコーチ",
"age" => 20,
"hobbies" => ["読書", "プログラミング"],
];
print_r($user);
出力結果は次のようになります。
Array
(
[name] => かつコーチ
[age] => 20
[hobbies] => Array
(
[0] => 読書
[1] => プログラミング
)
)
ネストした配列でも階層構造がひと目で分かるので、私は配列の中身を確認したいときは基本的にprint_rを使っています。
2つの使い分け方
簡単に使い分けの基準をまとめます。
| 関数 | 向いている場面 |
|---|---|
var_dump | 型まで含めて厳密に確認したいとき(数値か文字列か、nullかfalseかなど) |
print_r | 配列やオブジェクトの構造をざっくり把握したいとき |
迷ったときは、両方出力してみても問題ありません。
出力を見やすくするひと工夫
print_rやvar_dumpの出力は、HTML上ではインデントが崩れて1行に詰まって表示されることがあります。
そんなときは<pre>タグで囲むと、改行やインデントがそのまま反映されて読みやすくなります。
<?php
$user = ["name" => "かつコーチ", "age" => 20];
echo "<pre>";
print_r($user);
echo "</pre>";
私はこの<pre>で囲むひと手間を知らなかった頃、配列の中身がぐちゃぐちゃに表示されて余計に混乱していました。
たった数文字追加するだけで見やすさが劇的に変わるので、ぜひ覚えておいてください。
つまずきやすいポイント:dieやexitとの組み合わせ
出力しても画面が流れて見えない
var_dumpを書いても、その後の処理が続いて画面がどんどん流れてしまい、結局どこに何が表示されたのか分からなくなることがあります。
❌ Before:出力した後も処理が続いてしまう
<?php
$users = ["田中", "佐藤", "鈴木"];
foreach ($users as $user) {
var_dump($user);
// この後も大量の処理が続く…
}
echo "処理が完了しました";
// 大量の出力の中にvar_dumpの結果が埋もれてしまう
私も実際、ループの中にvar_dumpを入れたまま処理を最後まで走らせてしまい、大量のログの中から目的の出力を探すハメになったことがあります。
✅ After:dieやexitで処理をその場で止める
<?php
$users = ["田中", "佐藤", "鈴木"];
foreach ($users as $user) {
if ($user === "佐藤") {
var_dump($user);
die("ここで処理を止めて確認"); // 目的の箇所で処理を強制終了する
}
}
echo "処理が完了しました"; // ここまで到達しない
確認したい変数の直後にdieやexitを書いて処理を強制的に止めることで、その時点の状態だけに集中して確認できます。
俗に「dd(dump and die)」と呼ばれる手法で、Laravelなどのフレームワークには最初からdd()というヘルパー関数が用意されているほど、実務でもよく使われる考え方です。
一歩進んだデバッグ:Xdebugの導入
var_dumpだけでは限界がある理由
var_dumpは手軽ですが、確認したい箇所すべてに書いて回るのは手間がかかりますし、確認が終わったら消し忘れないように管理する必要もあります。
処理が複雑になってくると、「そもそもどこを通ってこの値になったのか」という処理の流れ自体を追いたくなる場面が増えてきます。
そこで登場するのが、XdebugというPHPの拡張機能です。
Xdebugでできること
Xdebugを導入すると、次のようなことができるようになります。
- コードの好きな行に「ブレークポイント」を設定し、そこで処理を一時停止できる
- 一時停止した状態で、その時点のすべての変数の中身を確認できる
- 処理を1行ずつ進めながら、値がどう変化していくかを追跡できる
- エラー発生時のスタックトレース(どの関数からどの関数が呼ばれたか)を見やすく表示してくれる
var_dumpが「特定の1点の値をスナップショットで見る」ツールだとすると、Xdebugは「処理の流れ全体を映画のように追いかける」ツールというイメージです。
導入の基本的な流れ
Xdebugの導入手順は環境によって異なりますが、大まかな流れは共通しています。
- お使いのPHP環境(バージョン・OS)に合ったXdebugのビルド済みファイルを用意する
php.iniにXdebugの設定を追記する- エディタ(VS Codeなど)に対応する拡張機能を入れて、PHPと接続する
; php.iniへの追記例
[xdebug]
zend_extension=xdebug xdebug.mode=debug xdebug.start_with_request=yes xdebug.client_port=9003
xdebug.mode=debugが、いわゆる「ステップ実行」を有効にするための設定です。
VS Codeの場合は「PHP Debug」という拡張機能を入れることで、エディタ上に停止ボタンやブレークポイントが表示され、ブラウザからアクセスするだけで自動的に処理が止まるようになります。
私が最初につまずいたポイント
正直に言うと、私が初めてXdebugを導入したときは、php.iniを編集したのに全く反応しませんでした。
原因は、PHPの設定ファイルが複数存在していて、実際に読み込まれているものとは別のファイルを編集していたことでした。
php --iniというコマンドを実行すると、実際に読み込まれているphp.iniのパスが表示されます。
php --ini
このコマンドで正しいファイルの場所を確認してから編集し直したところ、無事にXdebugが動くようになりました。
「設定を変えたはずなのに反映されない」ときは、まず読み込まれているファイル自体が正しいかを疑ってみてください。
まとめ
この記事のポイント
var_dumpは値と型を両方確認したいときに使うprint_rは配列やオブジェクトの構造をざっくり把握したいときに使う<pre>タグで囲むと出力が見やすくなるdieやexitと組み合わせて、確認したい箇所で処理を止めるのが実践的- 処理の流れを追いたくなったら、Xdebugでステップ実行を導入する
次に読むべき記事
デバッグの基本が分かったところで、次はこのシリーズで扱ってきたテーマの中から、初心者がよくつまずくポイントをQ&A形式でまとめます。
→ 次の記事:PHPのよくあるつまずきポイントQ&A集