memo.xight.org

日々のメモ

PHPの文字化け - 5つの誤解と5つの対策

Summary

設定すべき項目は以下.

;; Disable Output Buffering
output_buffering = Off

;; Set HTTP header charset
; default_charset = EUC-JP

;; Set default language to Japanese
mbstring.language = Japanese

;; HTTP input encoding translation is enabled.
mbstring.encoding_translation = off

;; Set HTTP input encoding conversion to auto
mbstring.http_input = pass

;; Convert HTTP output to EUC-JP
mbstring.http_output = pass

;; Set internal encoding to EUC-JP
mbstring.internal_encoding = EUC-JP

;; Do not print invalid characters
mbstring.substitute_character = none

mbstring.detect_order = SJIS,EUC-JP,JIS,UTF-8,ASCII

誤解1: default_charsetはデフォルトの文字コードのことではない.

default_charsetは,出力時にHTTPヘッダとして送信する文字コード名のこと.

default_mimetype = 'text/html'
default_charset = 'utf-8' の場合
header('Content-Type: text/html; charset:utf-8');

が自動的に実行される.

Content-Typeが固定されるため,default_charsetは使用すべきではない.

誤解2: languageパラメータは内部言語のことではない.

languageパラメータは,mb_send_mailを利用した際にのみ使用される.
また,mb_send_mailは文字コードの変換を指定できないため,使用すべきでない.
PEAR::Mailで代替可能.
よって,languageパラメータは実質的に意味をなさない.

誤解3: internal_encodingは内部エンコードのことではない.

internal_encodingはmbstring関数のデフォルトエンコードのこと.
mb_convert_kanaなどで変換元文字コードの指定がない場合に使用される.

変換元文字コードを固定にするため,
internal_encodingはソースコードの文字コードと揃えておくと良い.

誤解4: http_outputを指定しても,自動的に文字コードは変換されない.

http_outputとは,mb_output_handlerが実行された時の出力エンコード.
ob_start("mb_output_handler")

と指定して初めて使われる.
また,http_outputの動作条件は,出力がtext/htmlである必要がある.

誤解5: detect_orderでautoを指定してはいけない.

detect_orderとは,文字コードの自動検出の優先順位のこと.
未指定の場合は,"auto" という値になるが,
"auto" は "ASCII,JIS,UTF-8,EUC-JP,SJIS" に展開される.

マルチバイトを扱う際に,ASCIIが最初にある点が問題.
出力する文字コードを先頭にし,JISやASCIIは最後の方に設定する.

結論

対策1: default_charsetを設定しない.
対策2: mb_send_mailを使用しない.
対策3: internal_encodingをソースコードの文字コードと揃える.
対策4: http_outputを使用しない.
対策5: detect_orderは必ず指定する.

Reference

PHPの文字化けを本気で解決する - ぎじゅっやさん
http://hain.jp/index.php/tech-j/2007/02/13/%EF%BC%B0%EF%BC%A8%EF%BC%B0%E3%81%AE%E6%96%87%E5%AD%97%E5%8C%96%E3%81%91