ジャンルから探す

Web Design & Dev English

PHPで文字列を出力する方法|echo・console.log・error_logの使い分け

PHPで文字列を出力する方法を、出力先ごとに整理して解説します。

結論から書くと、画面に出すなら echo、ブラウザの開発ツールのコンソールに出すなら console.log() を埋め込む方法、画面を汚さずログに残すなら error_log() を使います。

デバッグのつもりで echo した文字が本番の画面に出てしまった、という事故はよくあります。出力先を使い分けられるようにしておくと、そもそもその事故が起きません。

この記事では3つの出力方法と、配列を確認するときの関数の選び方、そしてコンソール出力で見落とされがちなエスケープの注意点までまとめます。動作は PHP 8.5 で確認しています。

スポンサーリンク

出力先で使い分ける3つの方法

結論:何を確認したいかではなく、どこに出したいかで選びます。

▼出力方法の使い分け

方法 出力先 使う場面
echo 画面(HTML) そのまま表示したい値
console.log() を埋め込む ブラウザの開発ツール 画面を崩さず値を見たい
error_log() サーバーのログファイル 本番・非同期処理・APIの中

以下、それぞれ解説していきます。

echoを使って文字列を出力する

結論:echo は、渡した文字列をそのまま画面に出力します。PHPでいちばん基本的な出力です。

echo "出力したい文字列";

複数の値をカンマで並べて渡すこともできます。

$name = "りん";
echo "こんにちは、", $name, "さん";

変数の値を画面に出すときは、必ずエスケープしてください。ユーザーが入力した値をそのまま echo すると、HTMLタグやスクリプトがそのまま解釈されます。

// 危険:入力値がそのままHTMLとして解釈される
echo $comment;

// 安全:HTMLの特殊文字を実体参照に変換する
echo htmlspecialchars($comment, ENT_QUOTES, 'UTF-8');

PHP 8.1 以降は htmlspecialchars() の既定が ENT_QUOTES | ENT_SUBSTITUTE | ENT_HTML401 になったため、引数を省略してもシングルクォートまで変換されます。ただし明示しておくほうが、古い環境へ持っていったときに挙動が変わりません。

スポンサーリンク

HTMLのコード上でechoを使って出力する

結論:HTMLの中に値を差し込むときは、PHPの開始・終了タグで囲みます。短縮タグ <?= ?> を使うと echo を書かずに済みます。

<body>
    <?php
        echo "出力したい文字列";
    ?>
</body>

同じ内容を短縮タグで書くとこうなります。

<body>
    <?= htmlspecialchars($text, ENT_QUOTES, 'UTF-8') ?>
</body>

<?=<?php echo の短縮形です。PHP 5.4 以降は short_open_tag の設定に関係なく常に使えるので、テンプレートの中ではこちらのほうが読みやすくなります。

なお、ファイルの末尾に閉じタグ ?> は書かないのが定石です。閉じタグの後ろに改行や空白が残ると、それが出力に混ざってヘッダー送信のエラーになることがあります。

開発ツールのコンソールに出力する

結論:画面に出したくない値は、<script> タグを出力して console.log() に渡します。ブラウザの開発ツールのコンソールで確認できます。

配列やオブジェクトを確認したいときに向いています。画面のレイアウトを崩さずに中身を見られるので、CSSの調整中でも使えます。

<?php
  $data = ["name" => "りん", "tags" => ["php", "css"]];
  echo '<script>';
  echo 'console.log(' . json_encode($data, JSON_HEX_TAG | JSON_HEX_AMP | JSON_HEX_APOS | JSON_HEX_QUOT | JSON_UNESCAPED_UNICODE) . ')';
  echo '</script>';
?>

json_encodeにフラグを付ける理由

結論:フラグなしの json_encode() は危険です。値の中に </script> という文字列が入っていると、そこでスクリプトタグが閉じてしまい、続きがHTMLとして解釈されます。

たとえば、ユーザーが入力した文字列にこれが混ざっていると、任意のスクリプトを実行されます。JSON_HEX_TAG を付けると <>\u003C / \u003E に変換されるので、この経路が塞がります。

▼付けておくフラグ

フラグ 効果
JSON_HEX_TAG < > を変換する(これが必須)
JSON_HEX_AMP & を変換する
JSON_HEX_APOS ' を変換する
JSON_HEX_QUOT " を変換する
JSON_UNESCAPED_UNICODE 日本語をそのまま出す(読みやすさ用)

JSON_UNESCAPED_UNICODE だけは安全性ではなく可読性のためのフラグです。付けないと日本語が \u308a\u3093 のようなエスケープ表記になり、コンソールでは読めますが目視の確認がしづらくなります。

なお、この方法はHTMLを出力するページでしか使えません。Ajax で JSON を返すAPIや、CLIから実行するスクリプトの中で使うと、レスポンスに <script> が混ざって壊れます。そういう場所では次の error_log() を使ってください。

スポンサーリンク

画面に出さずログに残す(error_log)

結論:error_log() は、値をサーバーのエラーログに書き出します。画面にもレスポンスにも一切出ないので、本番環境やAPIの中でも安全に使えます。

$data = ["name" => "りん", "tags" => ["php", "css"]];

// 文字列をそのまま
error_log("ここまで到達しました");

// 配列は print_r で文字列にしてから渡す
error_log(print_r($data, true));

// JSON にすると1行で収まって grep しやすい
error_log(json_encode($data, JSON_UNESCAPED_UNICODE));

print_r() の第2引数に true を渡すのを忘れないでください。省略すると画面に出力してしまい、ログには「1」とだけ記録されます。

出力先は php.inierror_log で決まります。設定していない場合はウェブサーバーのエラーログに出ます。Apache なら error_log、nginx + PHP-FPM なら PHP-FPM のログを確認してください。

tail -f /var/log/php-fpm/error.log

配列の中身を確認する関数の選び方

結論:配列やオブジェクトの中身を見る関数は3つあります。型まで見たいなら var_dump()、構造を読みやすく見たいなら print_r()、コードとして貼り直したいなら var_export() です。

▼3つの関数の違い

関数 型の表示 文字列で受け取る 向いている用途
var_dump() あり(型と文字数も出る) できない 型の取り違えを疑うとき
print_r() なし 第2引数に true 構造をざっと見るとき
var_export() あり(PHPの記法で出る) 第2引数に true そのままコードに貼るとき

「値は入っているはずなのに条件分岐に入らない」といった場面では、var_dump() を使ってください。print_r() では文字列の "0" と数値の 0null と空文字の区別が付きません。

var_dump($value);
// string(1) "0"  ← 文字列の 0
// int(0)         ← 数値の 0
// NULL           ← null

画面に出したくない場合は、先ほどの error_log(print_r($data, true)) と組み合わせます。

デバッグ出力を本番に残さないために

結論:出力先を error_log() に統一しておくと、消し忘れても画面には出ません。

echovar_dump() による確認用の出力は、消し忘れるとそのまま本番の画面に出ます。特に var_dump() は変数の中身をすべて吐き出すので、内部のパスやIDが表に出てしまうことがあります。

確認用の出力は最初から error_log() で書く癖を付けておくと、この事故が起きません。どうしても画面に出したい場合は、開発環境でだけ動くように条件を付けてください。

if (getenv('APP_ENV') === 'local') {
    echo '<pre>' . htmlspecialchars(print_r($data, true), ENT_QUOTES, 'UTF-8') . '</pre>';
}

PHPのローカル環境を整えるところからやり直したい場合は、MacでPHPのバージョンを切り替える方法もあわせてどうぞ。Homebrew での切り替え手順と、切り替えが反映されないときの対処をまとめています。

Laravel など、フレームワークの中でデバッグする場面が多い場合は、Dockerを使ってLaravel/Blade環境構築からscss導入までで作った環境がそのまま使えます。