モバイル用でSJISに変換するclass

Movable TypeとかのCMSで、「DBで文字化けとかそういうのありそうだからCharsetはとりあえずSJISはやめとけ」って感じは普通にあると思うけど、モバイルサイトと連動させる時にauで化ける、みたいな(auだけじゃないけどauで苦情多い)。普通にSJIS以外でも読めるって機種も増えてるけど、その他を切り捨てるわけにもいかないっていう。これへの対処はいろいろとあるけど、PHPオブジェクト指向を勉強中なので今回はこんな風にしてみた。

mobile.php

<?php
class mobile{
  var $charset;
  function mobile(){//コンストラクタ
    //ここで機種判別とかやる(他で使う)
  }
  function fixCharsetFrom($charset){
    $this->charset=$charset;
    ob_start(array(&$this,'fixCharset'));
  }
  function fixCharset($t){
    return mb_convert_encoding($t,"sjis-win",$this->charset);
  }
  function display(){
    while(ob_get_level() > 1) {ob_end_flush();}
    header("Content-type: text/html");
    header("Content-length: ".ob_get_length());
    ob_end_flush();
  }
}
?>

MTのテンプレート(UTF-8で保存しとく)

<?php
require("mobile.php");
$mobile=new mobile();
$mobile->fixCharsetFrom("<MTPublishCharset>");
?><html>
<head><title>ブログだよ</title></head>
<body>
<MTEntryTitle><hr><MTEntryBody>
</body>
</html>
<?php
$mobile->display();
?>

クラスのメンバ関数をバッファリングのコールバック関数に指定するやり方を知らなかったから今回調べて勉強になった。メンバ関数display()でob_end_flush()をwhileにしているのはPHP: ob_end_flush - Manualを見たからだけど、今回の文字コード変換以外にも例えば絵文字をキャリア別に変換したりする関数を追加する場合にも、同じようにバッファリングを使うことでサクッといく。一番最後のob_end_flush()だけwhileから外してあるのは、Content-Lengthをきちんと吐かないといけないっていう仕様をどっかのキャリアが書いてたから。