Featured image of post Docker環境でPHPのbasename関数が日本語を消してしまう問題の解決方法

Docker環境でPHPのbasename関数が日本語を消してしまう問題の解決方法

Twitter ツイート Hatena Bookmark ブックマーク

Dockerで用意した環境のphpでbasename関数をつかって日本語文字が消えてしまう問題が発生していました。
Googleで検索すると大体は setlocale(LC_ALL, 'ja_JP.UTF-8'); すればいいと書いてあったので脳死で設定してみましたが、ダメでした。

1
2
3
4
5
setlocale(LC_ALL, 'ja_JP.UTF-8');

$test = basename("テスト.txt");
$test2 = basename("てすと.txt");
var_dump($test, $test2);

ちなみにASCII文字が含まれると日本語が削られないという謎現象が発生してて、よくわからんってなっていました。

ホスト側のPCでphpを実行したところ basename 関数を使っても問題はおきなかったのですが、なぜかDockerコンテナ側のphpで実行すると発生していました。

setlocaleが実はfalseを返してた

setlocale関数のマニュアル に以下の記載がありました。

setlocale() の戻り値は、 PHP が実行されているシステムに依存します。 システムの setlocale 関数が返す値を返すためです。

試しに var_dump(setlocale(LC_ALL, 'ja_JP.UTF-8')) を実行したところ結果はfalseが返ってきました。
正常な場合はどうなんだろうと思ってホスト側PHPで実行したところ以下のように文字列が返ってきました。

1
$ string(11) "ja_JP.UTF-8"

おそらくですがDocker側のlocaleの設定がうまくできてないのかと。

localeの設定をたしかめてみる。

Dockerコンテナに接続して locale コマンドを実行することで、localeの設定を確認できます。 試しに実行してみたところ以下のような結果に・・・。

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
$ locale
LANG=
LANGUAGE=
LC_CTYPE="POSIX"
LC_NUMERIC="POSIX"
LC_TIME="POSIX"
LC_COLLATE="POSIX"
LC_MONETARY="POSIX"
LC_MESSAGES="POSIX"
LC_PAPER="POSIX"
LC_NAME="POSIX"
LC_ADDRESS="POSIX"
LC_TELEPHONE="POSIX"
LC_MEASUREMENT="POSIX"
LC_IDENTIFICATION="POSIX"
LC_ALL=

ロケールがPOSIXになっていたため basename 関数でトラブルがおきていたわけですね・・・。

localeにja_JP.UTF-8を設定する

デフォルトのphp-fpmのコンテナはdebianなので以下のようにDockerfileに追加しました。

1
2
3
4
5
RUN apt-get update \
    && apt-get install libc-l10n locales \
    && locale-gen ja_JP.UTF-8 \
    && localedef -i ja_JP -c -f UTF-8 -A /usr/share/locale/locale.alias ja_JP.UTF-8 \
    && update-locale LANG=ja_JP.UTF-8 \

これでコンテナをビルドすれば日本語でも basename が正しく実行されます。

試しにlocaleコマンドで正しく設定されているか確認しましょう。

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
$ locale
LANG=
LANGUAGE=ja_JP:jp
LC_CTYPE="ja_JP.UTF-8"
LC_NUMERIC="ja_JP.UTF-8"
LC_TIME="ja_JP.UTF-8"
LC_COLLATE="ja_JP.UTF-8"
LC_MONETARY="ja_JP.UTF-8"
LC_MESSAGES="ja_JP.UTF-8"
LC_PAPER="ja_JP.UTF-8"
LC_NAME="ja_JP.UTF-8"
LC_ADDRESS="ja_JP.UTF-8"
LC_TELEPHONE="ja_JP.UTF-8"
LC_MEASUREMENT="ja_JP.UTF-8"
LC_IDENTIFICATION="ja_JP.UTF-8"
LC_ALL=ja_JP.UTF-8

まとめ

  • basenameで日本語文字列の処理がおかしい場合はsetlocaleを設定してみる
  • setlocaleは戻り値を必ずチェックする
  • localeコマンドでos側のlocale設定を確認する

参考

basenameすると先頭の日本語が消えてしまう
Docker: コンテナのlocaleを設定したい

comments powered by Disqus
Built with Hugo
テーマ StackJimmy によって設計されています。