文字化けを直すと PHP が動作せず,PHP を動作させると文字化けになってしまう問題が解決した。
このサイトの文字コードは基本的に EUC-JP で,一部に UTF-8 のページがある。UTF-8 のページでは PHP が動作している(nlog(n): Picasa の Web エクスポートに PukiWiki 風のコメント欄をつける)。PHP は,拡張子が .html の場合でも動作するように設定している(nlog(n): 拡張子を変更せずに MT を PHP 化)。当初はうまく動作していたのだが,いつの間にか UTF-8 のページが文字化けするようになってしまった(nlog(n): 文字化けを直すとPHPが動作しなくなる)。Apache のバージョンを疑ったが,原因は違うところにあった。
このサイトの構成で関係のある点は次の通り。
環境は Vine Linux 3.2 kernel-2.4.33-0vl0.9,apache-1.3.33-0vl2.3, php5-apache-5.2.0-0vl2 である。
これは,異なる文字コードのページが混在している場合に有効な設定である。
このサイトでは,拡張子が .php のファイルだけでなく,.html のファイルも PHP で動作するように設定している。基本は .htaccess に AddType ディレクティブを追加することで行う(nlog(n): 拡張子を変更せずに MT を PHP 化)。
PHP 化した際に,.htaccess の代わりに httpd.conf で設定してみたが,動作しなかったためそのまま放置していた。その後しばらくして UTF-8 のページに文字化けが発生した(nlog(n): 文字化けを直すとPHPが動作しなくなる)。当初は反映されなかった httpd.conf での AddType 設定が,何らかのタイミングで有効になり,それと同時に文字化けが始まったのではないかと推測される。
なぜなら,httpd.conf で .html を PHP に処理させるように設定すると,.htaccess 内で AddType で文字コード設定をしていても,PHP で設定されている Content-Type が強制的にヘッダについてしまうからである。つまり,Apache の文字コード設定よりも PHP の設定の方が優先されるのだ。
上述の理由により,nlog(n): Picasa の Web エクスポートに PukiWiki 風のコメント欄をつける を正しく動作させるには,.htaccess に次のように書いておけばよいことになる。特にこれは EUC-JP と UTF-8 のページが混在している場合だが,混在せず UTF-8 のページだけの場合でも有効である。
ポイントは,default_charset の設定である。default_charset で設定した文字列は,HTML レスポンスヘッダ内の「Content-Type: text/html; charset=」の後ろにそのまま表示される(PHP: コア php.ini ディレクティブに関する説明 - Manual)。この文字列は,最終的には Web ブラウザで利用されるため,大文字でも小文字でもよい。W3C の書式に習い,ここでは小文字にしている(W3C I18n article: Character encodings)。mbstring.internal_encoding は PHP が扱うものなので,マニュアルにある通り大文字とした(PHP: マルチバイト文字列関数 (mbstring) - Manual)。.htaccess で設定できる PHP ディレクティブは,PHP: php.ini ディレクティブ - Manual のうち,変更の可否が PHP_INI_ALL または PHP_INI_PERDIR となっているものである。
まず,Web ブラウザが文字コードを判定する基準についてみてみる。@IT:Javaの文字化け対策FAQ には次の解説がある。
HTML 4.01仕様では、Webブラウザが以下の優先順位で文字コードを決定することを規定している。
- HTTPにおけるContent-Typeヘッダのcharsetパラメータ
- HTML文書内のMETA宣言およびhttp-equiv属性で設定された、Content-Typeヘッダのcharsetパラメータ
- HTML文書内の各要素のcharset属性
ここで,数字が若いほど優先順位が高い。すなわち,Content-Type ヘッダの charset パラメータが最も優先される。
次に,サーバ側で Content-Type ヘッダをどのように設定しているかについて見てみたい。しかし,探し出せなかった。恐らく次のような動作をすると思われる。順序は上から下なので,下に行くほど優先度が高くなる。
ここまで書き終わったところで,タイムリーにはてブコメントをいただいた(はてなブックマーク - 徒栞 / 2007年01月16日)。すんごくタイムリー。そして的確である。
1つの拡張子に違うAddTypeを同時に適用はできないので、(1)AddType application/x-httpd-php htmlするならPHP側でContent-Typeヘッダを出力。(2)AddType "text/html; charset=.." htmlするならAddHandler application/x-httpd-php html とかでは。
2015年1月14日追記:
OS をアップグレードしたところ,またもやこの問題が発生し,そして解決しました (nlog(n): 拡張子 html で PHP を動作させているときの文字化け問題が復活)。
Master Archive Index
Total Entry Count: 1957