ヒアドキュメントとPHP_EOLとインクルードファイルでどはまりした話

同じコードにもかかわらずインクルードしたファイルで挙動が変化する。
まずヒアドキュメントを作成する。
$searchWordList = <<<EOT
abc
def
ghi
EOT;
検索対象の変数を設定する
$targetWord  = 'xxxdefxxx';
そして$searchWordListからexplodeして配列をつくり検索ワードに部分一致するものをヒットさせる。
この場合は配列の2番目の def が部分一致するのでそこでヒットしなければいけない。
そのexplodeのセパレーターで問題が発生。
PHP_EOL と \r\n で挙動が変わる。
インクルードPHPファイルでは \r\n で希望通り分割できるが、PHP_EOL では希望通り分割できていない。
逆に本体PHPファイルでは PHP_EOL で希望通り分割できるが、\r\n では希望通り分割できていない。
ちなみにWindowsにたてたPHPサーバーではどちらのセパレーターでもどちらのファイルでもヒットする。
インクルードPHPファイルの中身
echo '<div>↓開始インクルードファイル</div>';
echo '<div>インクルードするPHPファイルはWindowsで作成UTF-8 BOM無 CF+LF。apacheサーバーにアップロード。</div>';
echo 'このファイルでのPHP_EOLの中身は'.ord(PHP_EOL);
$searchWordList = <<<EOT
abc
def
ghi
EOT;
$targetWord  = 'xxxdefxxx';
echo '<br /><br /><div>開始 PHP_EOLでexplodeした配列で処理</div>';
$array = explode(PHP_EOL, $searchWordList);
foreach($array as $word) {
  if (strpos($targetWord ,$word) > -1) {
    echo '<div>PHP_EOLでヒット!!!</div>';
  }
}
echo '<div>終了 PHP_EOLでexplodeした配列で処理</div>';
echo '<br /><br /><div>開始 \r\nでexplodeした配列で処理</div>';
$array = explode("\r\n", $searchWordList);
foreach($array as $word) {
  if (strpos($targetWord ,$word) > -1) {
    echo '<div>¥r¥nでヒット!!!</div>';
  }
}
echo '<div>終了 \r\nでexplodeした配列で処理</div>';
echo '<div>↑終了インクルードファイル</div>';
検証結果インクルードPHPファイルをrequire_onceで読み込み

↓開始インクルードファイル
インクルードするPHPファイルはWindowsで作成UTF-8 BOM無 CF+LF。apacheサーバーにアップロード。
このファイルでのPHP_EOLの中身は10

開始 PHP_EOLでexplodeした配列で処理
終了 PHP_EOLでexplodeした配列で処理


開始 \r\nでexplodeした配列で処理
¥r¥nでヒット!!!
終了 \r\nでexplodeした配列で処理
↑終了インクルードファイル

インクルードPHPファイル終了


本体のPHPファイルはWindowsで作成UTF-8 BOM無 CF+LF。apacheサーバーにアップロード。
試しにインクルードPHPファイルの中身をそのまま本体PHPファイルにコピペして本体PHPファイル自身で実行する。
以下インクルードファイルと同一コードを本体のPHPで実行

↓開始インクルードファイル
インクルードするPHPファイルはWindowsで作成UTF-8 BOM無 CF+LF。apacheサーバーにアップロード。
このファイルでのPHP_EOLの中身は10

開始 PHP_EOLでexplodeした配列で処理
PHP_EOLでヒット!!!
終了 PHP_EOLでexplodeした配列で処理


開始 \r\nでexplodeした配列で処理
終了 \r\nでexplodeした配列で処理
↑終了インクルードファイル

原因

原因はインクルードPHPファイルの拡張子にありました。
FTPツールの転送でアスキーモードで転送する拡張子に入っていないためバイナリーモードで転送されていました。
FTPツールで該当する拡張子もアスキーモードで転送するように設定を変更する。もしくはアスキーモードで転送される拡張子に変更すれば問題は解決します。
ちなみにインクルードファイルはパーミッションを600に設定しておきましょう。そうしないと
https://code.fukasigi.net/php/heredoc_include.xxxこのように直接アクセスが出来てしまうのでセキュリティリスクになります。
このheredoc_include.xxxは駄目な例の見本として意図的にパーミッションを666のままにしています。
戻る

全体目次