このページは、著者がPHP4からPHP5にかけて、マルチバイトエンコーディングにおける文字化け・変換失敗・設定などのトラブルを自分なりに調査・解決し、その設定方法などの記録をトラブルシューティングとして役立ててもらえるよう構成したものです。しかし過去の記録でもあり、公式な文書ではないため、間違いがあるかもしれません。また内容・スクリプト例とも執筆中です、あしからず。最終更新:
特に指定がない場合※1 、以下の設定が理想の設定(例)となります。これはphpinfo()の出力結果より抜粋(日本語以外の部分は省略済み)したものです。php.iniを編集できる権限を持っていて、日本語を使う前提ならばphp.iniを編集するのが手っ取り早いでしょう。
またデータベースやファイルシステムとのやりとりすることも考えて、内部エンコーディングは早いうちにUTF-8かEUC-JPのどちらかに決めておきましょう。SJISは内部エンコーディングともデータベースとも不向きです。将来のことを考えるとUTF-8が一番お勧めです。
この例では著者の次のような環境をターゲットにしています。
※1 既成のスクリプトによっては、自主的にエンコーディング変換処理を行うために、自動変換を無効にしておくものがあります。そのような場合、このような自動変換にまかせる設定ではうまく動作しません。
Multibyte Support | enabled |
Japanese support | enabled |
HTTP input encoding translation | enabled |
Multibyte (japanese) regex support | enabled |
Directive | Local Value | Master Value |
---|---|---|
mbstring.detect_order | auto | auto |
mbstring.encoding_translation | On | On |
mbstring.func_overload | 0 | 0 |
mbstring.http_input | auto | auto |
mbstring.http_output | SJIS | SJIS |
mbstring.internal_encoding | UTF-8 | UTF-8 |
mbstring.language | Japanese | Japanese |
mbstring.script_encoding | auto | auto |
mbstring.substitute_character | none | none |
Multibyte Support | enabled |
Multibyte string engine | libmbfl |
HTTP input encoding translation | enabled |
Multibyte (japanese) regex support | enabled |
Multibyte regex (oniguruma) version | 4.4.4 |
Multibyte regex (oniguruma) backtrack check | On |
Directive | Local Value | Master Value |
---|---|---|
mbstring.detect_order | auto | auto |
mbstring.encoding_translation | On | On |
mbstring.func_overload | 0 | 0 |
mbstring.http_input | auto | auto |
mbstring.http_output | SJIS | SJIS |
mbstring.internal_encoding | UTF-8 | UTF-8 |
mbstring.language | Japanese | Japanese |
mbstring.strict_detection | Off | Off |
mbstring.script_encoding | auto | auto |
mbstring.substitute_character | none | none |
もしレンタルサーバなどでphp.iniを編集できなくても
Server API | Apache 2.0 Handler |
というように、Server APIのところにApache ... Handlerの表示がある場合、Apacheの拡張機能(モジュール)としてPHPが動作しているので、.htaccessファイルに次の記述をすれば大丈夫です。
php_value default_charset UTF-8
php_value default_mimetype text/html
php_value output_buffering 4096
php_value output_handler mb_output_handler
php_value mbstring.language Japanese
php_value mbstring.internal_encoding UTF-8
php_value mbstring.script_encoding auto
php_flag mbstring.encoding_translation On
php_value mbstring.http_input auto
php_value mbstring.http_output SJIS
php_value mbstring.detect_order auto
php_value mbstring.substitute_character none
php_value mbstring.func_overload 0
php_flag mbstring.strict_detection Off
ただし、PHPのコンパイル時点での設定により、
mbstring.script_encoding | auto | auto |
が有効にならない場合もあるので注意が必要です。→mbstring.script_encodingが有効にならない場合
またApacheの設定によっては.htaccessの使用が制限されている場合もありますので、その場合は他の方法を試すか、サーバ管理者に相談して下さい。
mbstring.script_encoding | auto | auto |
この表示になっていれば、PHPのスクリプトのエンコーディングが何であれ、自動的に変換して読み込んでくれるのでほぼ問題ありません。また思惑通りにならない場合はSJISやEUC-JP,UTF-8などの文字エンコーディングを指定してもよいでしょう。→ApacheのモジュールとしてPHPが動作している場合
しかし、いくら頑張って指定してもこの表示が出てこない場合もあります。これはPHPをコンパイルするときに--enable-zend-multibyteオプションが付けられていないためで、ini_set(),.htaccess,php.iniのいづれでもなす術がありません。バイナリインストールやレンタルサーバではよくありがちなパターンですが、これを解決するには、マルチバイト対応版バイナリのPHPをインストールするか、それが出来なければスクリプトのエンコーディングを
mbstring.internal_encoding | UTF-8 | UTF-8 |
の設定に合わせるしかありません。全てのPHPスクリプトのエンコーディングを揃えておきましょう。
また、スクリプトの先頭でdeclare( encoding="EUC-JP" );
という命令?を書いておくと良い、という情報をどこかで見かけましたが、私自身が挙動を理解できていないので取り上げないことにしました。
まず設定が次のようになっているか確認しましょう。
mbstring.encoding_translation | On | On |
mbstring.http_input | auto | auto |
mbstring.http_inputがautoでないとHTTP入力の「全自動」エンコーディング変換が行われません。SJISなどと設定できますが、あまり意味が無いような気がします。特殊なPHPスクリプトではpassを設定することもあります。これはバイナリデータを誤って変換されないようにするためですが、スクリプト中で自発的にエンコーディング変換をするためにpass設定するのは少し勿体無い気がします。またmbstring.encoding_translationはHTTP入力の自動エンコーディング変換を行うかどうかなので、当然Onにする必要があります。HTTP出力は?関係ないらしいですが・・・。
しかし、文字エンコーディングの設定は合っていて、スクリプトエンコーディングも内部エンコーディングも出力エンコーディングも問題ないのに、なぜかHTTP入力($GET,$_POST,$_REQUEST,$_FILESの一部)だけが文字化けする場合、PHPのバグ?仕様?※2 のせいかもしれません。PHP5.1.7以降?※3 ではHTMLのフォームでenctype="multipart/form-data"を指定するとHTTP入力の自動エンコーディング変換で失敗してしまうようです。この場合はenctype="multipart/form-data"を使わないか、もしくは次のようにして$_POSTと$_GET等を自分でエンコーディング変換してやればよいでしょう。$_REQUESTの合成順序は適当に修正して下さい。
<?php
// マルチパートの条件
define('HAVE_MULTIPART', (isset($_SERVER["CONTENT_TYPE"]) and strpos($_SERVER["CONTENT_TYPE"], "multipart/form-data;") === 0) );
// マルチバイトが自動変換されない問題の条件
define('HAVE_MB_PROBLEM', (HAVE_MULTIPART and ini_get('mbstring.encoding_translation') and ini_get('mbstring.http_input') != 'pass' and version_compare(PHP_VERSION, "5", ">=")) );
// PHP5でmultipart/form-data使用時、強制的にエンコーディング変換
if ( HAVE_MB_PROBLEM ) {
mb_convert_variables(mb_internal_encoding(), mb_detect_encoding(serialize($_POST), 'auto', true), $_POST);
mb_convert_variables(mb_internal_encoding(), mb_detect_encoding(serialize($_GET), 'auto', true), $_GET);
if ( is_array($_FILES) and count($_FILES) ) foreach ( $_FILES as $input => $hash ) {
mb_convert_variables(mb_internal_encoding(), mb_detect_encoding(serialize($_FILES[$input]['name']), 'auto', true), $_FILES[$input]['name']);
}
}
?>
2008.8.15: FreeBSD/amd64でのmb_convert_variables()の不具合に対応すべくスクリプトを修正しました。
※2 PHPマニュアルには次のように記載されています。マニュアル = 仕様どおりでないということで、私個人的にはバグだと思っています。
注意: PHP 4.3.3 以降、HTML フォームの enctype が multipart/form-data に設定され、かつ、 php.ini において mbstring.encoding_translation に On が指定されている場合、 POST データの変数とアップロードされたファイルの名前の文字エンコーディングは、 内部文字エンコーディングに変換されます。 ただし、クエリキーに関しては、変換されません。
※3 PHP5.1.6ではそんな現象は起きなかったという情報があっただけで、実際にどのバージョンが該当するのかはわかりません。また環境によってはなる場合とならない場合があるかもしれません。PHP4.3.2以前は別の原因の問題があるのでここでは触れないことにします。
2008.6.15: 私の環境、FreeBSD 6.1 amd64 と PHP 5.1.6 および 5.2.6で、HTTP入力の自動変換およびmb_convert_variables()
においてシフトJISから変換するとPHPがタイムアウトまでCPU使用率が100%になり応答がなくなるという現象が起きています。詳細は調査中です。
.htaccessもphp.iniも編集できない場合には、次のようなスクリプトを最初に実行すれば対応できます。一部の項目だけ変更したい場合は、その項目だけ実行しても構わないでしょう。$_REQUESTの合成順序は適当に修正して下さい。
<?php
//output_buffering=4096 , output_handler=mb_output_handler
ob_start("mb_output_handler" ,4096);
//mbstring.language=Japanese
mb_language("Japanese");
//mbstring.internal_encoding=UTF-8
ini_set("mbstring.internal_encoding", "UTF-8");
mb_internal_encoding("UTF-8");
mb_regex_encoding("UTF-8");
//mbstring.http_output=SJIS
ini_set("mbstring.http_output", "SJIS");
mb_http_output("SJIS");
//mbstring.detect_order=auto
ini_set("mbstring.detect_order", "auto");
mb_detect_order("auto");
//mbstring.substitute_character=none
ini_set("mbstring.substitute_character", "none");
mb_substitute_character("none");
//mbstring.encoding_translation=true , mbstring.http_input=auto
mb_convert_variables(mb_internal_encoding(), mb_detect_encoding(serialize($_POST), 'auto', true), $_POST);
mb_convert_variables(mb_internal_encoding(), mb_detect_encoding(serialize($_GET), 'auto', true), $_GET);
if ( is_array($_FILES) and count($_FILES) ) foreach ( $_FILES as $input => $hash ) {
mb_convert_variables(mb_internal_encoding(), mb_detect_encoding(serialize($_FILES[$input]['name']), 'auto', true), $_FILES[$input]['name']);
}
$_REQUEST = $_POST + $_FILES + $_GET + $_COOKIE;
?>
2008.8.15: FreeBSD/amd64でのmb_convert_variables()の不具合に対応すべくスクリプトを修正しました。
ただし、一部の設定はスクリプトが読み込まれた時点ですでに変更できないはずなので、変更できるのは内部エンコーディングと出力エンコーディングだけです。そのため、このスクリプトの後半ではHTTP入力の変数をエンコーディング変換しています。もちろんすぺてのPHPスクリプトのエンコーディングは内部エンコーディングに揃えておきましょう。
またこの方法ではあえて2つのやり方で同じ設定を行っています。一方のやり方だけだとphpinfo()で反映されない項目がありますが、実際の設定はmb_get_info()で確認することができます。PHPの設定によってはini_set()の実行を制限されている可能性もあり、エラーまたはワーニングが発生するかもしれません。
マルチバイトモジュール自体が組み込まれていなければ、マルチバイトの設定項目自体が表示されません。php.iniを次のように編集してマルチバイトモジュールを組み込む設定にします。ただしすでにマルチバイト機能が組み込まれている場合は二重に読み込もうとしてエラーを発生することになりますので、その場合は設定を変えてはいけません。また.htaccessの方法ではサーバエラーが発生するようです。
;UNIX系の場合
extension=mbstring.so
;Windowsの場合
extension=php_mbstring.dll
しかし、php.iniをどうしても編集できない場合には、次のようなスクリプトを最初に実行すれば対応できるかもしれません。ただしこの方法では、セーフモードや制限がかかっている場合は対応できませんので、可能ならば管理者に頼んでphp.iniの方法で組み込んでもらったほうが無難です。
<?php
if ( !extension_loaded('mbstring') ) {
$prefix = (PHP_SHLIB_SUFFIX === 'dll') ? 'php_' : '';
dl($prefix . 'mbstring.' . PHP_SHLIB_SUFFIX);
}
//続けて設定ファイルで設定変更できないのスクリプトを記述
?>
PHPがファイルやファイルシステムにアクセスする際にはエンコーディングの変換は行われません。というより、そのスクリプトだけが読み書きするファイルも内部エンコーディング、という考えなのかもしれません。従って、そのスクリプトだけが読み書きするファイルの場合は心配することはありません。
しかし、他のプログラムもアクセスするファイルや、マルチバイトを含むファイル名については注意が必要です。ファイルシステムのファイル名規則に合わせたり、他のプログラムやデータのエンコーディングに合わせて、自分でエンコーディング変換をする必要があります。
また、そのスクリプトだけが読み書きするファイルの場合であっても、サーバの引越しなどで内部エンコーディングが変わってしまえば当然文字化けを起こすことになるので、その時には一旦エンコーディング変換をする必要があります。
他の日本語表示は大丈夫なのに、データベースへ読み書きしたデータが文字化けすることがあります。これはデータベースとの文字エンコーディングの違いによるものです。
PHPがデータベースにアクセスする際にはエンコーディング変換は行われませんが、データベースとやり取りするエンコーディング(クライアントエンコーディング)とPHPの内部エンコーディングを同じにしておけば、エンコーディング変換の必要がないので全く心配ありません。クライアントエンコーディングの設定はデータベースサーバによりますのでここでは触れませんが、もしどうしてもクライアントエンコーディングとPHPの内部エンコーディングを統一できない場合は、自分でエンコーディング変換をする必要があります。
クライアントエンコーディングとデータベース自体のエンコーディング、またデータベースシステムの内部エンコーディングが別々に設定できるものがありますが、それらを統一できればパフォーマンスの向上になります。
MySQL4.1~5.0以降あたりでマルチバイトの設定で騒がれていて、次のように設定ファイルで設定してあげればよいという話もありますが、後半の設定はmysqlクライアントだけの設定で、PHPで使用するMySQLモジュールのクライアントエンコーディングを設定するわけではないという情報もあるようです。
[mysqld]
skip-character-set-client-handshake
[mysql]
default-character-set=utf8
そこで「SET NAMES utf8;
」のようなSQL文を発行しましょう。その時点からクライアントエンコーディングを設定できます。実際には必要な複数の設定が反映されますし、接続を閉じるまで有効です。PHPの内部エンコーディングと同じ設定でクライアントエンコーディングを設定してしまえば、データベースやテーブルのエンコーディングが何であれ問題無しのようなので、こちらのほうが確実です。
prototype.jsなどで使われる非同期通信などで文字化けしたり、データが消えることがありますが、これは基本的に通信にはUTF8を使うことが前提になっているようで、エンコーディングを合わせていないと文字化けします。PHPから送信する前にmb_http_output("UTF-8");とするとうまくいくでしょう。
実はマルチバイト対応のPHPでも、スクリプトの実行にmbstring.internal_encodingによる設定は全く関係ないらしいです。
えっ?
と思われた方もいるのではないのでしょうか。私も最初の頃だったらびっくりしたのではないかと思います。PHPのマニュアルにも「内部エンコーディング」という表現で書かれていますから、てっきりPHPの中のコビトさんがその設定を見て働いていそうなイメージがあります。でもマルチバイト設定をしなくてもPHPは動作しますよね・・・。
それではmbstring.internal_encodingは何の設定でしょうか。それは「PHPに文字列を正しく処理させるために、マルチバイト機能が前もって変換しておく時の文字エンコーディング」と考えてみてはどうでしょうか。UTF-8やEUC-JPはそのまま扱っても処理としては問題になることはありません。しかしシフトJISなどではそのまま扱うと何かと失敗することがあるので、「一旦UTF-8やEUC-JPに変換してから処理しよう」と考えます。これが内部エンコーディングの考え方なのです。
<?php
$v = "-裏-表";
echo "一覧表renewal 表new 表$v\n\n";
?>
例えばこのようなスクリプトを用意します。UTF-8やEUC-JPで保存してあると、マルチバイトの設定を何もしていない状態でも(文字化けはしますが)ちゃんと動作します。しかし、シフトJISでは文法エラーになります。これが「シフトJISなどではそのまま扱うことはできない」「PHPのスクリプト実行にはマルチバイトの設定は全く関係ない」ということであり、逆に「エンコーディングに依存する部分さえ気をつければマルチバイトに対応できる」と言えると思います。(すべての挙動を確認したわけではありません。)
余談になりますが、このスクリプトで文法エラーが発生するのは、「表」という漢字はシフトJISで表現すると「'\x95','\'
」というデータになります。その「'\'
」をPHPがエスケープに使ってしまうので、そこからおかしくなってしまうわけです。
HTTP入出力はマニュアルやいろいろなところで解説されていますが、意外とあっけない扱いされているのがスクリプトエンコーディングです。php.iniや.htaccess等でのmbstring.script_encodingで指定するしかないのですが、PHPをコンパイルするときに--enable-zend-multibyteオプションが付けられていないとこの設定も有効になりません。
他の設定はスクリプトでどうにかなるのに、なぜこの設定だけがこんなに融通が利かないのかというと、そもそもスクリプトを読み込む際の処理に関わるからで、他の拡張機能と違って早い段階で働くから、のようです。あまり詳しいことはわかりませんが、PHPをコンパイルする段階でそのオプションを決定しておかないと間に合わなかったのでしょう。と、思うしかありません(泣)。
しかも悲しいことに本家でダウンロードできるWin32バイナリはこのオプションが付けられずにコンパイルされています。是非、mbstring.encoding_translationのようにコンパイルオプションから設定ファイルに記述できるように頑張って頂きたいものです。
さて、私がスクリプトエンコーディングにこだわっている理由というのは、スクリプトの読み込みもPHPにとっては「一旦変換してから処理しよう」の重要な場面だからです。この機能さえきちんと働いていれば、UTF-8やEUC-JPはもちろん、シフトJISやJIS(本当?やったことないけど)でスクリプトを書いても大丈夫なのです。なのにこの機能が使えないためにわざわざ「内部エンコーディング」で統一してスクリプトを書かなければならないという事態になり、勿体無いやり方が広まっているような気がします。
「内部エンコーディング」で統一してスクリプトを書いていると、少し矛盾が生じる場合があります。全てUTF-8で書いているような場合は問題ないのですが、phpスクリプト以外のhtmlファイルやjsファイル、スタイルシートなど様々なファイルを扱う際にエンコーディングが揃っていないと、こちら側でも混乱しやすくなります。このことから考えると、実はスクリプトエンコーディングを出力エンコーディングに合わせた方が、全てのソースファイルのエンコーディングを揃えることが出来て楽になります。
というわけで、PHPバイナリの提供者の皆さん、レンタルサーバの管理者の皆さん、無知な私に代わって--enable-zend-multibyteオプション付きのPHPをよろしくお願いします。
PHPマニュアルの「XCVI. マルチバイト文字列関数 (mbstring)」のページには古い情報なのか、不適切な記述がされているような気がします。
オリジナル
mbstring モジュールに関係する設定オプションは 以下のとおりです。
個人的に追加
mbstring モジュールに関係する設定オプションは 以下のとおりです。
- --enable-zend-multibyte : スクリプトを読み込む際の文字エンコーディング変換を有効にします。この機能が有効で、かつ mbstring.script_encoding が指定されている場合、スクリプトは PHP に読み込まれる際に自動的に mbstring.internal_encoding の文字エンコーディングに変換されます。
オリジナル
表 174. mbstring 設定オプション
名前 デフォルト 変更可能な範囲 変更履歴 mbstring.language "neutral" PHP_INI_PERDIR PHP 4.3.0 から利用可能です。 mbstring.detect_order NULL PHP_INI_ALL PHP 4.0.6 から利用可能です。 mbstring.http_input "pass" PHP_INI_ALL PHP 4.0.6 から利用可能です。 mbstring.http_output "pass" PHP_INI_ALL PHP 4.0.6 から利用可能です。 mbstring.internal_encoding NULL PHP_INI_ALL PHP 4.0.6 から利用可能です。 mbstring.script_encoding NULL PHP_INI_ALL PHP 4.3.0 から利用可能です。 mbstring.substitute_character NULL PHP_INI_ALL PHP 4.0.6 から利用可能です。 mbstring.func_overload "0" PHP_INI_PERDIR PHP 4.2.0 から利用可能で、PHP <= 4.2.3 は PHP_INI_SYSTEM です。 mbstring.encoding_translation "0" PHP_INI_PERDIR PHP 4.3.0 から利用可能です。 mbstring.strict_detection "0" PHP_INI_ALL PHP 5.1.2 から利用可能です。
個人的に訂正
表 174. mbstring 設定オプション
名前 デフォルト 変更可能な範囲 変更履歴 mbstring.language "neutral" PHP_INI_PERDIR PHP 4.3.0 から利用可能です。mb_language() の使用で PHP_INI_ALL になりえます。 mbstring.detect_order mbstring.language によって変化します。 PHP_INI_ALL PHP 4.0.6 から利用可能です。 mbstring.http_input "pass" PHP_INI_PERDIR PHP 4.0.6 から利用可能です。 mbstring.http_output "pass" PHP_INI_ALL PHP 4.0.6 から利用可能です。 mbstring.internal_encoding NULL PHP_INI_ALL PHP 4.0.6 から利用可能です。 mbstring.script_encoding NULL PHP_INI_PERDIR PHP 4.3.0 から利用可能です。 mbstring.substitute_character NULL PHP_INI_ALL PHP 4.0.6 から利用可能です。 mbstring.func_overload "0" PHP_INI_PERDIR PHP 4.2.0 から利用可能で、PHP <= 4.2.3 は PHP_INI_SYSTEM です。 mbstring.encoding_translation "0" PHP_INI_PERDIR PHP 4.3.0 から利用可能です。 mbstring.strict_detection "0" PHP_INI_ALL PHP 5.1.2 から利用可能です。
オリジナル
Example#3 SJIS ユーザ用の php.iniの 設定
個人的に削除(いまいちSJISユーザ用という気がしない。)
multipart/form-dataを使用したフォームからリクエストされた際に、mb_get_info()で確認してみたところ、http_inputの値がPHPのバージョンや環境によって挙動が違います。--enable-zend-multibyteの影響は無さそうな気がします。でも$_POSTが変換されず(SJIS)に$_FILESが変換されている(UTF-8)のが不思議なところです。
PHP | OS等 | --enable --zend-multibyte |
クエリ無GET時 http_input |
POST時 http_input |
multipart/form-dataでの POST時 |
||
---|---|---|---|---|---|---|---|
http_input | $_POST | $_FILES | |||||
PHP 4.4.4 | FreeBSD 6.2 i386 | 有 | "" | "SJIS"=output | "SJIS"=output | 変換済み | 変換済み |
PHP 5.2.3 | linux | 無 | "ASCII" | 未確認 | "ASCII" | 無視 | 変換済み |
PHP 5.2.4 | FreeBSD 6.2 i386 | 有 | "" | "SJIS"=output | "ASCII" | 無視 | 変換済み |
PHP 5.2.5 | WinXP sp2 | 無 | "" | "SJIS"=output | "" | 無視 | 無視 |
現在、私はInternetExplorerはバージョン6を使っています。インターネットオプションの詳細設定で
常に UTF-8 として URL を送信する(再起動が必要)
という項目があります。てっきり私は「リクエストするときには日本語のクエリもUTF-8で送信してくれるのかな?」と思っていましたが、そうではなさそうでした。
<html><body>
<form action="" method=POST enctype="multipart/form-data">
<input type=text name=text value="シフトJISかもしれないけどそうとは限らない"><br>
<input type=file name=file><br>
<input type=submit><br>
</form><pre>
<?php
$a = mb_get_info();
var_dump($a);
echo 'mb_detect_encoding($_GET) => ', mb_detect_encoding(implode(" ",$_GET)), "\n";
echo 'mb_detect_encoding($_POST) => ', mb_detect_encoding(implode(" ",$_POST)), "\n";
?></pre>
</body></html>
このようなスクリプトを用意し、PHPのマルチバイトの設定もこのようにしておきました。
mbstring.encoding_translation | off |
mbstring.http_output | EUC-JP |
クエリ無しでリクエストすると、
mb_detect_encoding($_GET) => ASCII
mb_detect_encoding($_POST) => ASCII
となりました。ではそのままフォームを送信すると、
mb_detect_encoding($_GET) => ASCII
mb_detect_encoding($_POST) => EUC-JP
となりました。mbstring.http_output
を変えてみるとわかりますが、$_POST
の中身はページの文字エンコーディングに合っているようです。では現在のURLにそのまま「?text=シフトJISかもしれないけどそうとは限らない」を足してGETメソッドでリクエストします。
mb_detect_encoding($_GET) => SJIS
mb_detect_encoding($_POST) => ASCII
おや?$_GET
の中身はSJISですね。UTF-8ではありませんでした。ちなみにそのURLのままフォームを送信すると、
mb_detect_encoding($_GET) => SJIS
mb_detect_encoding($_POST) => EUC-JP
となります。$_GET
の中身はSJISのまま、$_POST
の中身はページの文字エンコーディングとなっています。これはPHPマニュアルにも書かれている通り、「HTTPからの入力は表示されたページの文字エンコーディングとは同じではない」ということになります。しかし、InternetExplorerの「常に UTF-8 として URL を送信する」オプションの意味がわかりません。URLエンコードした状態からUTF-8に変換、またはUTF-8という情報とともに送信しているということでしょうか・・・?。
どこかのページで「文字エンコーディングは出力と入力とで同じだから、かえって自動変換させないほうがいい」と書かれたのを見かけましたが、それはおそらくPOSTメソッドに限ったことだと思いますので注意して下さい。
Pentium D 820 + EM64TのマシンにFreeBSD 6.1 amd64版をインストールし、PHP5をインストールしました。するとmb_convert_variables()
で入力文字エンコーディングを'auto'にすると、実際の入力文字エンコーディングがシフトJISの時に限ってCPUの使用率が100%になり、そのままタイムアウトを迎えてしまいます。原因はわかりません。