CakePHP(1.2.1.8004)で携帯サイト用の絵文字を出力するメモ。

docomo、au、SoftBankの端末から接続があった場合、絵文字を出力してみます。
ビューなどに記述した絵文字コードをキャリアに対応した絵文字に変換します。

絵文字データとして、「絵文字データベースと相互変換マッピングデータベースのJSONファイルを公開します。 : アシアルブログ」で公開されているデータを使用させていただきます。(ありがとうございます。)

Index

  1. すること、しないこと
  2. 設定
  3. 絵文字コード定義
  4. 絵文字HTML記述
  5. 絵文字出力処理
  6. 表示サンプル
  7. ダウンロード

すること、しないこと

  • 携帯端末からの絵文字入力のことをいまは考えないことにします。
  • キャリアごとのビューやデータを作らず、3キャリア共通のデータ(htmlなど)に絵文字コードを埋め込みます。
  • PC用の絵文字表示はしないことにします。

設定

app/configディレクトリにpictogramディレクトリを作成し、その中に上記絵文字データのファイルを置きます。

JSONのデコードに、Zend_Jsonを使います。
Zend Framework(1.7.3)へのインクルードパスをapp/config/bootstrap.phpで設定することにします。

app/config/bootstrap.php 抜粋
PHP:
  1. // Zend Framework,PEARライブラリインクルードパス設定
  2. $lib_dirpath = '/PATH/lib';
  3. $include_path = ini_get('include_path');
  4. ini_set('include_path',
  5.         $include_path . ':' . $lib_dirpath . '/ZendFramework-1.7.3PL1-minimal/library' .
  6.         ':' . $lib_dirpath . '/pear/PEAR');
  7.  
  8. // 絵文字データを格納するディレクトリ
  9. define('PICTOGRAM_JSON_DIR',CONFIGS . 'pictogram');

PEARライブラリのパスの設定も.htaccessからapp/config/bootstrap.phpに移動しました。
CakePHPのシェル、タスクを使うつもりなので。

絵文字コード定義

次のような絵文字コードをhtmlなどに記述したり、データベースに格納することにします。

docomoの絵文字コード定義 [[emjI:docomo絵文字番号]]
auの絵文字コード定義 [[emjE:au絵文字番号]]
SoftBankの絵文字コード定義 [[emjS:softbank絵文字番号]]

docomo絵文字番号・au絵文字番号・softbank絵文字番号は、上記絵文字データで定義された、キャリアごとに振られた絵文字番号です。

[[emjI:1]]をhtmlに記述すると、docomoの絵文字「晴れ」に相当する絵文字に変換します。

絵文字HTML記述

絵文字コードを次のHTML記述に変換して出力します。

キャリア HTML記述 備考
docomo &#x[UNICODE]; 作ろうiモードコンテンツ:絵文字記述方法のUnicodeテキスト記述です。
au <img localsrc="絵文字番号"> auの絵文字番号はこちら
SoftBank ウェブコード

絵文字出力処理

AppControllerクラスのafterFilterメソッドで、出力HTMLに含まれる絵文字コードを絵文字(html記述用)に変換します。

追記 2009/02/11 20:00

auの絵文字出力を<img localsrc="番号">の形を止め、utf-8コードを出力するように変更しました。
au端末で絵文字が表示されるかどうかは不明です。

app/app_controller.php 抜粋
PHP:
  1. class AppController extends Controller
  2. {
  3. // ...
  4.   function afterFilter()
  5.   {
  6.     parent::afterFilter();
  7.     if (!$this->_isPcOnly) {
  8.       // 絵文字コードをキャリアごとの絵文字に置換して、出力する
  9.       $this->output = my_output_filter($this->output);
  10.     }
  11.   }
  12. // ...
  13. }

app/config/common_func.php 抜粋
PHP:
  1. function my_output_filter(&$string)
  2. {
  3.   include_once('Zend/Json.php');
  4.  
  5.   $pattern = '/\[\[emj([I,E,S]):([0-9]{1,4})\]\]/';
  6.  
  7.   $replacement = 'replace_emoji4web';
  8.  
  9.   $str = preg_replace_callback($pattern, $replacement, $string);
  10.   return $str;
  11. }
  12.  
  13. function replace_emoji4web($matches)
  14. {
  15.   if (!isset($matches[1]) || !isset($matches[2])) {
  16.     if (isset($matches[0])) {
  17.       return $matches[0];
  18.     }
  19.     return '';
  20.   }
  21.   $from = '';
  22.   if ($matches[1] == 'I') {
  23.     $from = 'docomo';
  24.   }
  25.   else if ($matches[1] == 'E') {
  26.     $from = 'ezweb';
  27.   }
  28.   else if ($matches[1] == 'S') {
  29.     $from = 'softbank';
  30.   }
  31.   else {
  32.     return $matches[0];
  33.   }
  34.  
  35.   $val = '';
  36.   if (UAGENT_KIND == UAGENT_DOCOMO) {
  37.     $to = 'docomo';
  38.   }
  39.   else if (UAGENT_KIND == UAGENT_AU) {
  40.     $to = 'ezweb';
  41.   }
  42.   else if (UAGENT_KIND == UAGENT_SB) {
  43.     $to = 'softbank';
  44.   }
  45.   else {
  46.     return '<!-- ' . $matches[0] . ' -->';
  47.   }
  48.   $val = get_emoji_html($from,$to,$matches[2]);
  49.   if ($val === false) {
  50.     return $matches[0];
  51.   }
  52.   return $val;
  53. }
  54.  
  55. function get_emoji_html($from,$to,$num)
  56. {
  57.   static $docomo_convert = null;
  58.   static $ezweb_convert = null;
  59.   static $softbank_convert = null;
  60.   static $docomo_emoji = null;
  61.   static $ezweb_emoji = null;
  62.   static $softbank_emoji = null;
  63.  
  64.   $target_num = $num;// 絵文字番号
  65.   if ($from != $to) {
  66.     if (!${$from . '_convert'}) {
  67.       $path = PICTOGRAM_JSON_DIR . '/' . $from .'_convert.json';
  68.       if (!is_file($path)) {
  69.         return false;
  70.       }
  71.       $data = file_get_contents($path);
  72.       if ($data === false) {
  73.         return false;
  74.       }
  75.       ${$from . '_convert'} = Zend_Json::decode($data);
  76.     }
  77.  
  78.     if (!isset(${$from . '_convert'}[$from][$num])) {
  79.       return false;
  80.     }
  81.  
  82.     $row = ${$from . '_convert'}[$from][$num];
  83.  
  84.     if (!isset($row[$to])) {
  85.       return false;
  86.     }
  87.     $target_num = $row[$to];
  88.     if (strpos($target_num,';') !== false) {
  89.       $arr = explode(';',$target_num);
  90.       if (is_array($arr) && isset($arr[0])) {
  91.         $target_num = $arr[0];
  92.       }
  93.     }
  94.     if (!is_numeric($target_num)) {
  95.       return $target_num;// 文字
  96.     }
  97.   }
  98.  
  99.   if (!${$to . '_emoji'}) {
  100.     $path = PICTOGRAM_JSON_DIR . '/' . $to .'_emoji.json';
  101.     if (!is_file($path)) {
  102.       return false;
  103.     }
  104.     $data = file_get_contents($path);
  105.     if ($data === false) {
  106.       return false;
  107.     }
  108.     ${$to . '_emoji'} = Zend_Json::decode($data);
  109.   }
  110.  
  111.   if (!isset(${$to . '_emoji'}[$to][$target_num])) {
  112.     return false;
  113.   }
  114.   $emoji_data = ${$to . '_emoji'}[$to][$target_num];
  115.   return make_emoji_str($to,$emoji_data);
  116. }
  117.  
  118. function make_emoji_str($to,&$emoji_data)
  119. {
  120.   if ($to == 'docomo') {
  121.     if (!isset($emoji_data['unicode'])) {
  122.       return false;
  123.     }
  124.     if (!ctype_alnum($emoji_data['unicode'])) {
  125.       return false;
  126.     }
  127.     $str = '&#x' . $emoji_data['unicode'] . ';';
  128.     return $str;
  129.   }
  130.   else if ($to == 'ezweb') {
  131.     if (!isset($emoji_data['utf-8'])) {
  132.       return false;
  133.     }
  134.     if (!ctype_alnum($emoji_data['utf-8'])) {
  135.       return false;
  136.     }
  137.     $str = pack('H*',$emoji_data['utf-8']);
  138.     return $str;
  139.   }
  140.   else if ($to == 'softbank') {
  141.     if (!isset($emoji_data['webcode'])) {
  142.       return false;
  143.     }
  144.     if (!ctype_alnum($emoji_data['webcode'])) {
  145.       return false;
  146.     }
  147.     $str = pack('H*','1B24' . $emoji_data['webcode'] .'0F');
  148.     return $str;
  149.   }
  150.   return false;
  151. }

JSONデータを接続のあるたびに読み込んでいます。
非効率そうなので、適当なところでキャッシュを使うなどするつもりでいます。

表示サンプル

「・・・から接続しています。[[emjI:1]] [[emjE:1]] [[emjS:1]] [[emjI:1]]」というテキストをトップページのビューに記述したとします。

PCからFirefoxでトップページに接続すると、絵文字は表示されません。
htmlソースに、「PCから接続しています。<!-- [[emjI:1]] --> <!-- [[emjE:1]] --> <!-- [[emjS:1]] --> <!-- [[emjI:1]] -->」というように、絵文字コードはコメントアウトで出力されます。

iモードHTMLシミュレータⅡの場合は、次のような表示です。

絵文字出力サンプル

ダウンロード

(2009/02/11 20:00)ファイルを差し替えました。
auの絵文字出力方法を変更しました。
(au端末での絵文字表示は確認しておりません。)

アーカイブへのリンクを「ダウンロード(「CakePHPで携帯サイトを作る」のサンプル)」に移動しました(2009/02/11)。

関連投稿

Tags: , , ,

コメントをどうぞ