導入
続報
昨日サイトを再デプロイしたところ、ページ上部とブラウザの枠の間に幅の広い隙間ができてしまった。最初はCSSの問題かと思いきや、開発者ツールを開いてみると<body>タグの中に謎のが紛れ込んでおり、さらに<head>の内容がすべて<body>の中に入ってしまっていた。

異常箇所
百度で調べてみると、時間がなくてWindows付属のメモ帳でPHPファイルを編集したのが原因だった。メモ帳はBOM付きUTF-8(UTF-8 with BOM)で保存するため、このBOMヘッダーがPHPファイルの先頭に入ってしまう。PHPは<?php ?>の外にある文字をデフォルトで出力してしまうため、結果としてページにが余計に出力されてしまう。また、UTF-8 with BOMは<head>の内容を<body>内に解析させてしまうこともある。
を消すには、BOMなしUTF-8(UTF-8 without BOM)で上書き保存し直せばよい。
問題はPHPで起きたのだから、PHPで解決するという自給自足の精神で、こんなものも見つけた。
ここに載っていたPHPコードをドキュメントルートに置いてアクセスすると、すべてのファイルのBOMヘッダーを自動で除去できる。ただしファイル数が多いと実行時間がかかるため、ファイルタイプを判定してPHPファイルだけを対象にする機能を追加した。以下が新しいコードだ。
<?php
header('Content-Type: text/html; charset=utf-8');
$directory = isset($_GET['dir']) ? $_GET['dir'] : '.';
$removeBom = isset($_GET['remove']) && $_GET['remove'] == 1;
echo '現在の検索ディレクトリ:' . htmlspecialchars($directory) . '。現在の設定:';
echo $removeBom ? 'BOMを検出して除去する<br />' : 'BOM検出のみで除去しない<br />';
scanDirectoryForBom($directory, $removeBom);
function scanDirectoryForBom($directory, $removeBom) {
if (!is_dir($directory)) {
echo '無効なディレクトリ:' . htmlspecialchars($directory) . '<br />';
return;
}
if ($dh = opendir($directory)) {
while (($file = readdir($dh)) !== false) {
if ($file !== '.' && $file !== '..') {
$filePath = $directory . '/' . $file;
if (is_file($filePath) && pathinfo($filePath, PATHINFO_EXTENSION) === 'php') {
echo 'ファイル: ' . htmlspecialchars($filePath) . checkAndHandleBom($filePath, $removeBom) . '<br />';
} elseif (is_dir($filePath)) {
scanDirectoryForBom($filePath, $removeBom);
}
}
}
closedir($dh);
} else {
echo 'ディレクトリを開けません:' . htmlspecialchars($directory) . '<br />';
}
}
function checkAndHandleBom($filePath, $removeBom) {
$contents = @file_get_contents($filePath);
if ($contents === false) {
return ' <font color="red">ファイルを読み取れません</font>';
}
$bom = "\xEF\xBB\xBF";
if (substr($contents, 0, 3) === $bom) {
if ($removeBom) {
$newContents = substr($contents, 3);
if (rewriteFile($filePath, $newContents)) {
return ' <font color="green">BOMを検出し自動除去しました</font>';
} else {
return ' <font color="red">BOMを検出したが除去できません</font>';
}
} else {
return ' <font color="red">BOMを検出しました</font>';
}
} else {
return ' BOMは見つかりませんでした';
}
}
function rewriteFile($filePath, $data) {
if (file_put_contents($filePath, $data, LOCK_EX) === false) {
return false;
}
return true;
}
?>
予防法?クソメモ帳でPHPファイルを編集するなってことだ。でないと俺みたいに一晩棒に振ることになるぞo(TヘTo)