現象
#1854 Fixed the UTF-8 and long path support in the streams on Windows. が PHP 7.1.0 Alpha 2 に マージ されました。
- 最大パス長が2048バイトになりました。
- 今まで、
get_file_contents
の引数などのパス文字列のエンコーディングは、日本語版Windowsの場合、CP932
でしたが、これが、INIディレクティブ(internal_encoding, default_charset, zend.multibyte) に依存するようになりました。(RFC) - コンソールのコードページがやんわり対応されました。
(※ PHP 7.1 UPGRADE NOTES の 12. Windows Support も参照)
この対応により、間接的に日本語パス(0x5c問題)が解決されますが、既存のPHPソースコードにて、パス文字列のエンコーディングを操作していたり、0x5cをエスケープしていた場合は、 個別に修正が必要です。
対策(及び確認項目)
対策方針候補
- 設定もアプリケーションも全て
UTF-8
にする(推奨) - php.ini の default_charset を
CP932
にする。(影響範囲に注意) - 個別に
ini_set('default_charset', 'CP932');
(コンソール出力が乱れる可能性あり) - 個別に
mb_convert_encoding('日本語.txt', 'UTF-8', 'CP932')
(緊急応急処置として)
※ 基本的に 1.
で対応(したい)。大量のPHPソースコードを Shift_JIS(CP932) にしていた場合など、 他も検討。
影響のありそうなケース(既存のPHPソースコードのチェック対象)
※ Case 2
以降の例では、file_get_contents
の引数のみですが、 fopen
, file
などパス文字列に関連する全ての処理がチェック対象です。
Case 1: コンソール出力時に文字コードを変換している場合
<?php
if (PHP_OS === 'WIN32' || PHP_OS === 'WINNT') {
ob_start(function($buffer) {
return mb_convert_encoding($buffer, 'CP932', 'UTF-8');
});
}
echo '日本語';
/* vim:set fenc=utf8 ff=unix: */
ソースコードがUTF-8の場合、 ob_start
ごと不要。PHP5も対応しときたい場合は以下
<?php
if (((PHP_OS === 'WIN32') || (PHP_OS === 'WINNT'))
&& (version_compare(PHP_VERSION, '7.1.0') < 0)
) {
ob_start(function($buffer) {
return mb_convert_encoding($buffer, 'CP932', 'UTF-8');
});
}
echo '日本語';
/* vim:set fenc=utf8 ff=unix: */
Case 2: パスの文字列のエンコーディングを変更していた場合。
<?php
echo file_get_contents(mb_convert_encoding('日本語.txt', 'CP932', 'UTF-8'));
/* vim:set fenc=utf8 ff=unix: */
以下のようにエンコーディング変更ロジックを削除。
<?php
echo file_get_contents('日本語.txt');
/* vim:set fenc=utf8 ff=unix: */
Case 3: パスの文字列の 0x5c をエスケープしていた場合。
<?php
echo file_get_contents(mb_convert_encoding('表\.txt', 'CP932', 'UTF-8'));
echo file_get_contents(addcslashes(mb_convert_encoding('表.txt', 'CP932', 'UTF-8'), '\\'));
/* vim:set fenc=utf8 ff=unix: */
このエスケープ処理も削除。
<?php
echo file_get_contents('表.txt');
echo file_get_contents('表.txt');
/* vim:set fenc=utf8 ff=unix: */