「表示安全文字列生成」とは何をするものか
ここで言う「表示安全文字列」は、ざっくり言うとこういう文字列です。
画面に出してもレイアウトが壊れない。
ログに出してもビューアが変にならない。
HTML やターミナルで「意図しない意味」を持たない。
つまり、「人間が読むために安全で、扱いやすい形に整えた文字列」です。
元の文字列をそのまま出すのではなく、ログ・画面向けに「前処理」をまとめてやるユーティリティがあると、実務ではかなり便利です。
どんな問題から守りたいのか
HTML 表示での問題
ブラウザにそのまま文字列を出すと、< や > をタグとして解釈されてしまいます。
<script>alert(1)</script>
これをそのまま出すと、XSS(スクリプト実行)の原因になります。
なので、画面表示用には必ず htmlspecialchars でエスケープする必要があります。
ログ表示での問題
ログに「制御文字」や「極端に長い文字列」が混ざると、こうなります。
ログビューアが崩れる。
grep しづらい。
1 行が長すぎて、他の情報が見えなくなる。
なので、ログ用には「制御文字を落とす」「長さを制限する」といった前処理が欲しくなります。
コアとなる「表示安全文字列」ユーティリティの設計
やりたいことを分解する
表示安全文字列を作るとき、よくやる処理はだいたい次のようなものです。
前後の余計な空白を削る(trim)。
制御文字を除去する。
必要なら改行を残すか、スペースに変える。
長すぎる場合は、一定の長さで切って「…」を付ける。
HTML に出すなら htmlspecialchars でエスケープする。
これを毎回バラバラに書くのではなく、「1 本の関数にまとめる」のがユーティリティの発想です。
実装例① ログ向けの表示安全文字列
改行は残さず、1 行に収めたい場合
ログの 1 行メッセージとして使うことを想定して、
「改行も含めて制御文字を全部落とし、長さを制限する」関数を作ります。
/**
* ログ向けの表示安全文字列を生成する
*
* - 前後の空白をトリム
* - 制御文字(改行含む)を削除
* - 長すぎる場合は末尾を「...」で省略
*/
function to_safe_log_string(string $value, int $maxLength = 200): string
{
// 前後の空白を削る
$value = trim($value);
// 制御文字(0x00-0x1F, 0x7F)をすべて削除
$value = preg_replace('/[\x00-\x1F\x7F]/', '', $value) ?? '';
// 長さ制限(マルチバイト対応)
if (mb_strlen($value, 'UTF-8') > $maxLength) {
$value = mb_substr($value, 0, $maxLength, 'UTF-8') . '...';
}
return $value;
}
PHP使い方の例です。
$raw = $_POST['comment'] ?? '';
$logMessage = to_safe_log_string($raw);
error_log('comment=' . $logMessage);
PHPここでの重要ポイントは、「ログに出す前に必ずこの関数を通す」と決めてしまうことです。
そうすると、「変な制御文字」「異常に長い文字列」がログを壊すリスクをかなり減らせます。
実装例② 画面表示向けの表示安全文字列
改行は残して、HTML として安全に出したい場合
画面に出すときは、「改行は残したい」「HTML として安全にしたい」というニーズが多いです。
その場合は、こういう関数にします。
/**
* 画面表示向けの表示安全文字列を生成する
*
* - 前後の空白をトリム
* - 改行以外の制御文字を削除
* - 長すぎる場合は末尾を「...」で省略
* - HTML エスケープした上で、改行を <br> に変換
*/
function to_safe_html_string(string $value, int $maxLength = 200): string
{
$value = trim($value);
// 改行(LF, CR)は残し、それ以外の制御文字を削除
$value = preg_replace('/[\x00-\x09\x0B\x0C\x0E-\x1F\x7F]/', '', $value) ?? '';
// 長さ制限
if (mb_strlen($value, 'UTF-8') > $maxLength) {
$value = mb_substr($value, 0, $maxLength, 'UTF-8') . '...';
}
// HTML エスケープ
$escaped = htmlspecialchars($value, ENT_QUOTES, 'UTF-8');
// 改行を <br> に
return nl2br($escaped);
}
PHP使い方の例です。
$raw = $_POST['comment'] ?? '';
echo to_safe_html_string($raw, 500);
PHPここでの重要ポイントは、「エスケープと整形の順番」です。
テキスト整形(制御文字除去・長さ制限)
→ HTML エスケープ(htmlspecialchars)
→ 改行を <br> に変換(nl2br)
この順番を守ることで、「XSS を防ぎつつ、見た目も整った表示」ができます。
どこに組み込むかで安全性が変わる
「呼び出し側で毎回やる」は危険
毎回 trim して、preg_replace して、htmlspecialchars して…と書いていると、
どこかで「やり忘れ」が必ず出ます。
ログ出力の一部だけ生文字列。
画面の一部だけエスケープ漏れ。
こういう「穴」を防ぐために、「表示用に文字列を出すときは必ずこの関数を通す」と決めてしまうのが大事です。
例えば、ビュー層で共通のヘルパーとして使う、
ロガーのラッパーの中で必ず to_safe_log_string を通す、などです。
まとめ:今日からの「表示安全文字列生成」ユーティリティ
表示安全文字列生成の本質は、「人間が読む場所に出す前に、文字列を“安全で扱いやすい形”に整える」ことです。
ログ向けには、制御文字除去+長さ制限。
画面向けには、制御文字除去+長さ制限+HTML エスケープ+改行処理。
これらをユーティリティ関数にまとめておけば、「毎回バラバラに気をつける」必要がなくなります。
最後に、ログ用と画面用の 2 本をもう一度並べておきます。
function to_safe_log_string(string $value, int $maxLength = 200): string
{
$value = trim($value);
$value = preg_replace('/[\x00-\x1F\x7F]/', '', $value) ?? '';
if (mb_strlen($value, 'UTF-8') > $maxLength) {
$value = mb_substr($value, 0, $maxLength, 'UTF-8') . '...';
}
return $value;
}
function to_safe_html_string(string $value, int $maxLength = 200): string
{
$value = trim($value);
$value = preg_replace('/[\x00-\x09\x0B\x0C\x0E-\x1F\x7F]/', '', $value) ?? '';
if (mb_strlen($value, 'UTF-8') > $maxLength) {
$value = mb_substr($value, 0, $maxLength, 'UTF-8') . '...';
}
$escaped = htmlspecialchars($value, ENT_QUOTES, 'UTF-8');
return nl2br($escaped);
}
PHPもし、あなたのプロジェクトで「ログにそのまま生文字列を突っ込んでいる」「ビューで直接 $_POST を echo している」ような箇所があれば、そこがこのユーティリティを差し込むベストポイントです。
その 1 ステップを挟むだけで、「表示まわりの事故」はかなり減らせます。
