PHPでiモード用XHTMLを出力する際のトラブルと、トラブル対策としてPHPにパッチを当てる方法を紹介します。
ディノの過去の案件で実際にあったことなのですが、携帯向けにXHTMLのコンテンツを表示する際に、PHPで意外なトラブルが発生することがあります。具体的には、下記の状況でmb_output_handlerによる文字エンコーディング変換が効きません。
- ドコモ携帯向けにXHTMLを出力する
- Content-Typeを「application/xhtml+xml」とする必要がある(※1)
- mbstringで外部エンコーディングをSJIS-winに変換したい
- mb_output_handlerでの文字エンコーディング変換が「text/*」のときにしか有効にならない(※2)
実際、このような状況は十分考えられます。携帯向けのコンテンツをXHTML+CSSで作成することは今後どんどん増えてくるはずですので、Content-Typeを「application/xhtml+xml」とするしか無いでしょう。一方で、もうしばらくは下位機種のためのHTMLをSJIS-winで出力する必要があるでしょうから、外部エンコーディングを全てSJIS-winで統一するのが現実的です。
独自パッチの適用
上記の問題への対策として、ob_ナントカ関数を使って自力で頑張ってもいいのですが、我々はPHPにパッチを当ててしまうことにしました。下記がそのパッチです。(実際にパッチを当てるときは次のリンクを保存してください:php5-mbstring-xhtml-patch)
--- php-5.2.5/ext/mbstring/original_mbstring.c Mon Sep 24 20:51:36 2007 +++ php-5.2.5/ext/mbstring/mbstring.c Mon Mar 03 18:27:06 2008 @@ -1484,7 +1484,8 @@ /* analyze mime type */ if (SG(sapi_headers).mimetype && - strncmp(SG(sapi_headers).mimetype, "text/", 5) == 0) { + (strncmp(SG(sapi_headers).mimetype, "text/", 5) == 0 || + strncmp(SG(sapi_headers).mimetype, "application/xhtml+xml", 21) == 0)) { if ((s = strchr(SG(sapi_headers).mimetype,';')) == NULL){ mimetype = estrdup(SG(sapi_headers).mimetype); } else {
念のためパッチの手順も紹介します。同じディレクトリにphpのソースのtar玉とパッチを用意します。
$ tar xjf php-5.2.5.tar.bz2 $ cd php-5.2.5/ $ patch -p1 < ../php5-mbstring-xhtml-patch.txt
あとは普段通りにmakeすればOKです。PHP 5.2.5のソースコードに対するパッチとして作っていますが、ソースコードをパッと見たところでは、PHP 5.0.0から5.2.5まで全てに同じパッチが当たるかと思います(万一動作しなくても責任は取れませんが…)。
ディノでは過去の案件でこのパッチを実際に利用しています。また、他社さんでも同じ対応をしているところがあると聞きました。ご参考まで。
参考文献
- AngelicWing Diary - [php mobile symfony] 携帯向けコンテンツで大はまり
ディノ社内で実際にハマった人(tsukimiya)が事件直後に書いたものです。 - XHTMLのcontent-typeについて - XREA&CORE SUPPORT BOARD
似た状況で、PHP側で自前で文字エンコーディングを変換しています。 - ※1の根拠
MIMEタイプ
XHTMLのMIMEタイプは、application/xhtml+xmlとします。
- ※2の根拠
Content-Type: ヘッダが送信されると出力文字 コード変換は無効となります。
ただし、header() により”Content-Type: text/*” を送信した場合には、テキストが送信されるとみなし、文字コード設定に 基づいて出力文字コード変換を行います。

コメント / トラックバック 1 件
[...] 株式会社ディノさんのブログ「携帯向けXHTMLを出力する場合に便利なPHPのパッチ」でPHPのソースに直接パッチを当ててる模様。 [...]
コメントする