第14回 Smartyでケータイサイトを作ってみる - Smarty講座

PHP講座 HTML×CSS 初級編

yossy先生のSmarty講座

Lecutures on PHP

第14回 Smartyでケータイサイトを作ってみる (その3)

 このエントリーをはてなブックマークに追加

書き込みされた絵文字の変換は……

さて続いては、POSTされた掲示板への書き込みをどうするか? です。
方針として、POSTされた内容を以下の手順で変換して、そのデータを管理します。

  • <>&"などをエスケープ
  • {}をエスケープ
  • 絵文字を{emoji}関数に変換する

yossy先生POSTされた内容を表示する際に、先ほど作成した絵文字変換テンプレート関数{emoji}を使いたいところですが、POSTされた内容をテンプレートファイルにあらかじめ生成しておくなどしないと、そのままでは呼び出すことは出来ません。

前回説明したSmarty3であれば、stringリソースを使って表示することは出来ます。
同様の処理がSmarty2でも出来ないでしょうか?

というわけで、ここではグローバル変数の値をテンプレートとして解析するためのリソースプラグインが公開されているので、これを使ってみます。

http://api.zikula.de/__filesource/fsource_Smarty_plugins_includesclassesSmartypluginsresource.var.php.html

上記URLで公開されているソースを、plugins/resource.var.phpという名前で保存してください。

このプラグインの使い方ですが、テンプレートとして解析したい文字列をグローバル変数に入れ、それをSmartyクラスのfetchメソッドに渡します。
すると、変数の内容をテンプレートとして解析、変換した結果が返ってきます。

$emoji_tpl = '{emoji code=hare}';
$emoji = $smarty->fetch('var:emoji_tpl');

これを使うことで、{emoji}関数に置き換えられた書き込みも正しく絵文字に変換されて表示できそうです。

ではPOSTされたデータをエスケープし{emoji}タグへ変換する処理を書いてみます。

htdocs/post.php

  1  if($_SERVER['REQUEST_METHOD'] == 'POST'){
  2      
// エスケープ処理
  3      
$name escape($_POST['name']);
  4      
$content escape($_POST['content']);
  5      
$address escape($_POST['address']);
  6  
  7      
// 絵文字をタグに置換
  8      
$emoji_tbl EmojiTable::getInstance();
  9      
$agent Net_UserAgent_Mobile::singleton();
 10      if(
$agent->isDoCoMo()){
 11          
$carrier 'docomo';
 12      }   
 13      elseif(
$agent->isEZweb()){
 14          
$carrier 'au';
 15      }   
 16      elseif(
$agent->isSoftBank()){
 17          
$carrier 'softbank';
 18      }   
 19      else{
 20          
$carrier null;
 21      }   
 22  
 23      
$name    mb_convert_encoding($emoji_tbl->toTag($name$carrier),  'UTF-8''SJIS-win');
 24      
$address mb_convert_encoding($emoji_tbl->toTag($address$carrier),  'UTF-8''SJIS-win');
 25      
$content mb_convert_encoding($emoji_tbl->toTag($content$carrier),  'UTF-8''SJIS-win');
 26  
 27      
// 登録(snip)
 28  
}
 29  
 30  function 
escape($str)
 31  {
 32      
// <>&をエスケープ
 33      
$str htmlspecialchars($strENT_QUOTES'Shift_JIS');
 34  
 35      
// {}をエスケープ
 36      
mb_regex_encoding('SJIS-win');
 37      
$str mb_ereg_replace('{''&#123;'$str);
 38      
$str mb_ereg_replace('}''&#125;'$str);
 39  
 40      return 
$str;
 41  }

yossy先生ここでは掲示板の書き込みとして、name,content,addressの3つの値がPOSTされるとします。まず<>&をエスケープしています。Smartyテンプレートで修飾子escapeを呼んでエスケープ処理をしたいところですが、今回は出力するSmartyタグを生成する必要があるので、この時点でエスケープします。そしてSmartyタグのデリミタである{}もエスケープします。

次に先ほど作成したEmojiTableクラスのtoTagというメソッドを呼んでいます。このメソッドで絵文字をSmartyタグの{emoji}へ変換します。そして変換した結果を内部処理コードであるUTF-8に戻しています(EUC-JPを使っている方はここを書き換えてください)。変換した結果をDBなどへ登録する処理へ渡します。

ではタグ変換する処理はどうなるでしょうか? 先ほど作成したEmojiTable.class.phpに処理を追加していきます。

libs/EmojiTable.class.php(先ほどのソースに追記)

  1      public function toTag($content$carrier null)
  2      {
  3          if(
$carrier == 'docomo'){
  4              return 
$this->_docomoToTag($content);
  5          }
  6          elseif(
$carrier == 'au'){
  7              return 
$this->_auToTag($content);
  8          }
  9          elseif(
$carrier == 'softbank'){
 10              return 
$this->_softbankToTag($content);
 11          }
 12          else{
 13              return 
$content;
 14          }
 15      }
 16  
 17      protected function 
_docomoToTag($content)
 18      {
 19          if(empty(
$content)){
 20              return 
$content;
 21          }
 22  
 23          
$old_content $content;
 24          
$new_content '';
 25  
 26          while(
true){
 27              if(
mb_strlen($old_content) == 0){
 28                  break;
 29              }
 30  
 31              
$chr mb_substr($old_content01'SJIS-win');
 32              
$old_content mb_substr($old_content1mb_strlen ($old_content), 'SJIS-win');
 33              
$new_content .= preg_replace_callback('/(\xF8[\x9F-\xFC])|(\xF9[\x40-\xFC])/'array($this'_replaceDocomo'), $chr);
 34          }
 35  
 36          return 
$new_content;
 37      }
 38  
 39      protected function 
_replaceDocomo($matches)
 40      {
 41          if(empty(
$matches[0])){
 42              return 
'';
 43          }
 44   
 45          
$emoji_sjis16 strtoupper(bin2hex($matches[0]));
 46          return isset(
self::$_docomo_to_code[$emoji_sjis16]) ?  '{emoji code='.self:: $_docomo_to_code[$emoji_sjis16].'}' self::UNKNOWN_CHAR;
 47      }
 48  
 49      
protected static $_docomo_to_code array(
 50          
'F89F' => 'hare',
 51          
'F8A0' => 'kumori',
 52          
'F8A1' => 'ame',
 53          
'F8A2' => 'yuki',
 54          
'F8A3' => 'kaminari',
 55                  :
 56                  :
 57      ); 

今回はDoCoMoの絵文字変換処理だけ紹介します(_docomoToTag)。1文字ずつ取得し、正規表現で絵文字かどうかを判別します。ケータイからPOSTされるデータはShift-JISなので、先ほど{emoji}関数で作成したテーブルのコードはそのままでは使えません。なので、Shift-JISのコードに対応したテーブルを用意する必要があります(_docomo_to_code)。DoCoMoの絵文字の範囲をここでは1バイト目がF89F~F8FC、2バイト目がF940~F9FCで判定しています。

この正規表現にマッチした文字をbin2hexで16進文字列化し、かつそれが変換テーブルに登録されていたら{emoji}タグへ置換します。

では、登録したデータを表示したいと思います。先ほど紹介したvarリソースプラグインを用います。

// グローバル変数$name, $address, $contentに書き込まれた内容が格納されているとします
$smarty->assign('name', $smarty->fetch('var:name'));
$smarty->assign('address', $smarty->fetch('var:address'));
$smarty->assign('content', $smarty->fetch('var:content'));
$smarty->display('show.tpl');

yossy先生これで書き込まれた内容の絵文字タグが変換され、Smartyテンプレート内に記述され、そしてアウトプットフィルタでShift-JISに変換され、正しくケータイにも表示されるようになります。

今回、ケータイ対応のための各キャリアごとの対応の説明など細かい部分は端折りましたが、Smartyでケータイサイトを作成するためのヒントととして活用していただければと思います。

というわけで昨年末に連載再開してから8回、トータルで全14回の連載となりましたSmarty講座も今回で終了となります。 つたない説明で分かりづらいところもあったかもしれませんが、この連載が皆さんのWeb開発のヒントとしてお役に立つことが出来ていたら幸せです。

  • yossy先生

本名:吉武 正史

パッケージ系ソフトウェア会社で、自然言語処理系の研究やWebアプリケーション、検索連動型広告などの開発に従事。 2006年末にフリーランスとして独立し、現在はPHPによるWeb開発の業務を中心に、コンサルティングや執筆活動などを展開。
サイトURL:http://freeative.jp/

ご意見・感想フォーム

今回の「yossy先生のSmarty講座」への評価・ご意見があればご記入下さい。

評価:
ご意見・感想:

  



Pick Up Q&A

Q
動的なURLを静的に見せる方法
 このエントリーをはてなブックマークに追加 
A
普通に考えて、mod_rewrite でしょうね。 http://www.nishishi.com/blog/2006/01/mod_rewrite_url.html...

>>続きを読む

GETのままでは検索エンジンのロボットが拾ってくれなかったためにSEO対策として有効だと言われていますね。

▲解説者:岡本(アシアル株式会社 教育コーディネーター兼 システムエンジニア)