gallu’s blog

エンジニアでゲーマーで講師で占い師なおいちゃんのブログです。

使ってはいけない

mb_convert_encodingにて。第三引数であるfrom encodeは、省略もしちゃいけなければautoも禁止でございます。
半角カタカナを使う時に。
…状況設定しだいでは。えらいことになります orz


以下加筆。
っつか調査終了。
とりあえず前提条件として、文字コードについて軽く。
半角カタカナに絞った文字コードは以下のとおり。


sjis
0xA1-0xDF


euc
0x8EA1-0x8EDF*1


utf-8
EFBDA1-EFBDBF と EFBE80-EFBE9F*2


さて。とりあえず問題を「半角カタカナのみの文字列の場合」に絞ってみます。
平たく答えを返すと「自動判別ができない」のがほぼ現状です。
面倒なので端的に書くと。文字コードマッピングが重なりまくってるために「どっちかである」と確定することができない状態になってしまいます。具体的には、0xa1 0xa1という「EUCの文字」が存在し、「0x8ea1」という「Shift-jisの文字」が存在します。UTF-8の領域も一緒。くもの巣は自分で書いてちょ。
ああ念のため。たとえば「0xb1 0xb1 0xb1」なら「奇数なんだから多分shift jisの半角カナじゃね?」というほどにインテリジェントな機能は、とりあえず現状確認しているPHP5.2.5までの範囲ではないようです。で、それでもEUC変換すると「最後の1バイトなんかへんだから切り捨てちゃえ」と切り取られ、文字列が常に偶数文字化するという不思議な現象がおまけでついてきます orz


とりあえず色々と思うところはあるのですが(ってかいわゆるguessルーチンであるmb_detect_encodingをもうちょっと仕様的にどうにかして欲しいのですが具体的にはちゃんと確立を配列で返してくれるとか)。
ひとつには「Accept-Charset(通常はformエレメントのaccept-charsetアトリビュート値)を設定してもらう」ってのがあるのですが、特に携帯においてサポートされているかは限りなく疑問です(未調査)。
ふたつには「どこまでいっても誤検出の可能性」が付きまといます。


で…まぁ解法ってほどのものでもないんですが。
まず「mb系の自動検出でautoは禁物」これはmust。
ひとつは「postなりgetなりの値を一通りjoin(PHPだとimplodeですな)つなげてから推測」。文字数が多いほうが正解にたどり着きやすいので。
次点が、いわゆるヒンティング情報をhiddenなりで持たせる。便利ではあるのですが「忘れた瞬間にNG」なのが微妙。
で、このあたりを踏まえてとりあえずひとつの例を。GETのケースとかその他かなりアバウトにはしょってるので、空気だけ感じ取りつつmakeしなおしてください(一応MWには実装予定です)。

// 入力はshift-jisの可能性が高いだろうから優先順位もそっちにあわせる
mb_detect_order('sjis-win,eucjp-win,SJIS,EUC-JP,JIS,UTF-8,ASCII');

// チェック
if (false !== empty($_POST('hinting'))) {
  // ヒンティング文字列があればそれを基準にする
  $input_encode = mb_detect_encoding($_POST('hinting'));
} else {
  // なければ全体をマリっと使う
  $input_encode = mb_detect_encoding(implode('', $_POST));
}

…まぁ多言語でもいえるはずのTipsなのですが。この辺ってつい意識からはずしちゃいがちだし実際はずしてたので、めも。
# …でもさぁこーゆーところちゃんとフォローしてこその「初心者のための言語」ちゃうん?

*1:一部サイトで0x8E21-0x8E5F、とかなってますが、上述が多分正解だと思います

*2:なんで間がすっ飛んでるのか微妙なぞですがこうなってます