アシアルの中の人が技術と思いのたけをつづるブログ

symfonyの携帯絵文字プラグインを作りました。

タグ [  Tech  symfony  plugin  携帯  ]
こんにちは、亀本です。

最近はあつまろ☆ねっとで携帯のことをあれこれやっているのもあって、携帯回りの事に妙に詳しくなってきました。

あつまろ☆ねっとは携帯向けの掲示板とメーリスを備たサイトとして考案していたので、必然的に絵文字周りは
・HTMLコーディング時の容易な入力
・最低3キャリアの絵文字相互変換
・auからのメール絵文字の解析
等が必要とされることになり、やっぱしっかり作らないとだめだなぁ、と思ってあつまろ☆ねっと開発の傍らで絵文字ライブラリの作成を行っていました。

で。。。最初は普通のライブラリとして作成していたんですが

  1. ( ゚д゚) > 他にも似たようなのあるだろうから、symfonyプラグインにすりゃいんじゃね?

という何処からともなく湧き出た声に従って、symfonyのプラグインとして実装してみました。

前からずーーーと作りかけのものが放置プレイ状態になっていたんですが、きっかけもあって一通りプラグインとして用をなすところまで作りました。

ファイルはこちら:
sfPictogramMobilePlugin-0.0.1.tgz

バージョンがやたらと低いですが、エラー処理とかテストがないとか、そういうもろもろがあるので0.0.1で行きました。
動作自体は、それなりにちゃんと動きます。


インストールは、symfonyのプロジェクトルートで
  1. symfony plugin-install http://blog.asial.co.jp/data/sfPictogramMobilePlugin-0.0.1.tgz

としてください。
あとは、使用したい任意の場所でfactoryメソッドを使って

  1. $picObject = sfPictogrmMobile::factory($carrier, $type);
としてやれば、$carrierで指定した携帯キャリアの絵文字オブジェクトが得られます。
$typeというのは、この絵文字オブジェクトで利用する携帯絵文字の'sjis'などの文字コードの種類です。これらはそれぞれ、
  1.  - $carrier
  2.  --- $type
  3.  
  4.  - 'docomo'
  5.  --- 'sjis'
  6.  --- 'utf-8'
  7.  - 'ezweb'
  8.  --- 'sjis'
  9.  --- 'utf-8'
  10.  --- 'jis-email'
  11.  - 'softbank'
  12.  --- 'sjis'
  13.  --- 'utf-8'
という値をとることができます。それぞれの値の意味は・・・わかってください(^^;


一応、使用する際の想定としてはNet_UserAgentMobileなどでキャリア判定を行うことを前提に考えているので、今のところ自前での判定機能は持っていません。


で、機能の説明をしておくと、このsfPictogramMobileには大別して2つの機能があって

・絵文字バイナリを丸ごと取得(テンプレート作成用)
・絵文字データ変換(ユーザ投稿データ解析用)

の2つがあります。
まず前者ですが、これは上述のように取得した絵文字オブジェクトを
  1. $emoji = $picObject->getFormattedPictogramsArray();

とすると、DoCoMoの絵文字番号をキーにした各キャリアの絵文字データが取得できます。
どんな対照表になるかは、DoCoMoの絵文字変換対照表を参照してください。これの左はじの番号がキーになります。
====
追記:リンク切れしていました。
新しいDoCoMoの絵文字変換対照表はこちら

あとは、これをtemplate側に引き渡して

  1. <?= $data->emoji[1] ?>

みたいに指定してやれば、picObject生成時に指定した各キャリアの絵文字が表示されます。
自分がテンプレートを作成するときに、うーん各キャリア毎にいちいち一覧表見たり、絵文字選んだり、&#XXXXXX;なんて入力する値調べたりするのめんどくせええええええ><、と思ったので、こういう実装になりました。
こうすると、3枚のテンプレートを作成することになるのは避けられないにせよ、絵文字を統一的に(しかも直感的にわかりやすい番号で)扱えるので、煩雑な入力作業が減らせます。

ちなみに、getFormatttedPictogramsArrayメソッド(我ながら長いネーミング(^^;)の引数にキャリア名を与えてやれば、キーにするキャリアを変更することができます。
  1. // たとえば。。。こうするとezwebの表に従った絵文字データが返ってくる。
  2. $emoji = $picObject->getFormattedPictogramsArray('ezweb');

そのため、この引数もキャリア判定に従って切り替えてあげれば、それぞれのキャリアを別々に扱うことができるので、好きな方を選んでもらえればよいかと思います。


===============

次に、絵文字のデータ変換ですが、現在のところ各キャリアのShift_JIS、UTF-8と、auメールのISO-2022-JPに対応しています。

使い方なんですが、Shift_JIS・ISO-2022-JPとUTF-8でちょっとだけ違います。
一応、これには理由があるですが、それは後ほど。

Shift_JISおよびISO-2022-JP(auのemail受信のみ)を扱う場合には、
データ入力時にconvertメソッドを、データを引き出して表示するときにrestoreメソッドを使います。

  1. $convert_data = $picObject->convert($input_data);


  1. $view_data = $picObject->restore($convert_data);

これはそれぞれ、convertメソッドでShift_JISおよびISO-2022の絵文字を内部用の識別コードに置き換え、restoreメソッドで各キャリアの絵文字に復元しています。

なお、内部コードに直しているという性質上、データベースなどに格納する場合には実際の文字数よりも多くの文字数が必要になってしまうので、注意してください。


次に、UTF-8の場合の使用方ですが、これはもっと容易でデータ入力時には特に何もせず、データを引き出して表示する際にreplaceメソッドを使います。
  1. $view_data = $picObject->replace($input_data);

なぜデータ入力時には何もする必要がないかというと、各キャリアのUTF-8の定義領域に理由があります。
UTF-8の絵文字定義領域は、3キャリアともUnicodeの私的領域にそれぞれがかぶらないように定義されているため、UTF-8で保存をする場合には特別な工夫を凝らす必要はありません。
正確には、auとSoftBankは公式発表ではかぶりがあるのですが、ありがたい事にauが内部的に使っている絵文字コードがこの重複を回避する領域に存在しています。

そのため、絵文字の文字コードを解析するだけでどのキャリアの何の絵文字なのかを判別できるので、表示の際に1度だけ切り換えてやれば話が済みます。


UTF-8とShift_JISの使い方が違うのは、この使い勝手を優先したことと、技術ブログを各時間がもうそろそろタイムリミットになったこと。。。orz
なので、そのうちUTF-8でもShift_JISのような内部コードへ直す形式のサポートや、入力側をヘルパーとして整備する、などなど追加していきたいと思います。

==========
実際のところ、このライブラリはあつまろ☆ねっとの作成から派生したので、動作サンプルはあつまろ☆ねっとを見てもらう方が手っ取り早いです。メールとか。

ただ、あつまろ☆ねっとで使用しているものから内部仕様もかなり大きく書き換えたので、もしかすると逆に変な動作しちゃうところがあるかも。。バージョンダウン(汗


なお、symfonyのプラグインと銘打ってはいますが、今のところException以外はsymfonyに依存していませんので、Exception周りを書き換えてlibの中をひととおりrequireすれば、symfony以外でも特に問題なく使用できます。


まぁ、たぶん車輪の再発名だったりもすると思いますが、symfonyで使えるプラグインということで、ぜひご活用ください。

コメント

    • すばらしいライブラリの提供ありがとうございます!
      UTF-8の場合も内部コードに変換できるととてもうれしいです。バージョンアップ期待しています!
    • >みかんさん
      ありがとうございますー。
      暇をみてちょこちょこと改良していきたいと思います。
    • 使いやすいライセンス提示plz(何
    • >ELFさん
      ぴえぇ><。。。
      ライセンスとか難しい(汗

      とりあえず、現バージョンはsymfony本体と同等のライセンスに準拠するということで。。。
    • DoCoMoの絵文字変換対照表 のリンクが切れているようです。
    • >通りすがりさん
      すいません、見落としていました><
      ありがとうございます。修正しました!
    • とても便利なpluginありがとうございます!
      ただ、使い方がいまいちよくわかっていません。。
      フィルターで以下のようなコードだとsoftbankだけうまく動きます。ユーザから入力された絵文字を相互変換して表示するにはどのように修正したらいいでしょうか?ご教授いただけると嬉しいです。

      class myMobileFilter extends sfFilter
      {
      public function execute ($filterChain)
      {
      $request = $this->getContext()->getRequest();
      $response = $this->getContext()->getResponse();

      require_once('Net/UserAgent/Mobile.php');
      $objAgent = Net_UserAgent_Mobile::singleton();

      if ($this->isFirstCall())
      {

      //アクションでも使用できるようAttributeにセットしておく
      $this->getContext()->getRequest()->setAttribute('agent', $objAgent);

      //これは自作クラス
      $objMobile = new mobileCheck();

      //携帯端末の場合
      if ($objMobile->isMobile($objAgent))
      {
      if ($objAgent->isDoCoMo()) {
      $response->setContentType('application/xhtml+xml;charset=Shift_JIS');
      $carrier = 'docomo';
      $pictogram = sfPictogramMobile::factory($carrier, 'sjis');
      $this->encodingParams('SJIS','UTF-8', $pictogram);
      }
      if ($objAgent->isVodafone()) {
      $carrier = 'softbank';
      $pictogram = sfPictogramMobile::factory($carrier, 'utf-8');
      }
      if ($objAgent->isEZweb()) {
      $carrier = 'ezweb';
      $response->setContentType('application/xhtml+xml;charset=Shift_JIS');
      $response->setHttpHeader('Expires', "Thu, 01 Dec 1994 16:00:00 GMT");
      $response->setHttpHeader('Last-Modified', gmdate('D, d M Y H:i:s').' GMT');
      $response->setHttpHeader('Cache-Control', 'no-cache,must-revalidate');
      $response->setHttpHeader('Cache-Control', 'post-check=0,pre-check=0', false);
      $response->setHttpHeader('Pragma', 'no-cache');
      $pictogram = sfPictogramMobile::factory($carrier, 'sjis');
      $this->encodingParams('SJIS','UTF-8', $pictogram);
      }

      } else {

      $carrier = 'docomo';
      }
      $request->setAttribute('pictogram', $pictogram);
      $request->setAttribute('agent', $objAgent);
      $request->setAttribute('carrier', $carrier);
      }

      // execute next filter
      $filterChain->execute();

      $content = $response->getContent();

      if ($objAgent->isVodafone()) {
      $content = $request->getAttribute('pictogram')->replace($content);
      }

      if ($objAgent->isDoCoMo() || $objAgent->isEZweb()) {
      $content = mb_convert_encoding($content, 'Shift_JIS');
      $content = $request->getAttribute('pictogram')->restore($content);
      }
      $response->setContent($content);

      }
      protected function encodingParams($from,$to, $pictogram){
      if ($to !='' && $from !='' && $from != $to ){
      $params=$this->getContext()->getRequest()->getParameterHolder()->getNames();
      //print "<html><body>";
      foreach ($params as $param){
      $in=$this->getContext()->getRequest()->getParameter($param);
      //print $param.":".$in."<br>";
      $this->getContext()->getRequest()->setParameter($param, $pictogram->convert(mb_convert_encoding($in,$to,$from)));
      }
      //print "</body></html>";
      //exit;
      }
      }
      }
    • > stastaさん
      がっつりソースが崩れてしまって、なんだかわからない感じになっていますが(^^;

      たぶん、$pictogramを取得したあとにencodingParamsしている、その中の実装がおかしいんじゃないかと思います。

      mb_convert_encodingしてからconvertしていますが、これだとSJISをUTF-8にしてから、そのあとSJIS絵文字を内部処理用のコードに置き換える、ということになっているので、あべこべです。
      SJIS絵文字オブジェクトでconvert() -> mb_convert_encoding() -> UTF-8絵文字オブジェクトでrestore()
      という順に使っていただけば、変換できます。
      (ちょっと重いですが。。。)

      symfonyでモバイルをゴネゴネする方法について、簡単にまとめたスライドを
      http://handsout.jp/slide/721
      に置いてありますので、ぜひご参考になさってください。
    • お返事ありがとうございます!
      スライドも見たのですがうまくいかず。。
      がんばってみます!

コメントフォーム

認証
captcha_key
 

トラックバック