[Symfony2]入出力の文字エンコードを変換してみよう Symfony Advent Calender JP 2011 – 6日目-

Posted under php,Symfony2 by uechoco on 火曜日 6 12月 2011 at 10 : 00 : 00

@uechocoです。Symfony Advent Calendar JP 2011の6日目の記事です。@fivestrさんからのバトンタッチです。

日本Symfonyユーザー会に所属するスタッフとして、勢いで申し込んでみたものの、
普段職場でSymfonyを使ってないのでネタ探しに苦労しました。

そういえば去年のSymfony Advent 2010 : ATNDでは[Symfony2]PEAR::Net_UserAgent_MobileをDIコンテナから呼び出すという記事を書きました。
今年も似たような領域で、ガラケー向けのWebサイト開発で使えるかもしれないテクニックとして、入出力される値やコンテンツの文字コードを変換する方法をご紹介します。

symfony 1.x系ではMojavi由来のフィルタチェインの機構がありましたので、
MobileEncodingFilterなどのクラスを作って、入出力の前後でエンコードの変換をかませるというのが一般的だったかと思います。

Syfmony2系ではフィルタチェインという概念はなくなってしまいました。
代わりに処理の所々にイベントが定義されていて、リスナーを登録しておくと自動的にディスパッチしてくれるようなイベントドリブン方式に変わりました。

今回はSymfony2のHttpKernel機構に標準で設定されているkernel.requestイベントとkernel.responseイベントのリスナークラスとしてMobileEncodingListenerを作り、入出力のエンコード処理を行なっています。今回はSymfonyに標準で同梱されているAcme\DemoBundleの中に作成する前提です。

MobileEncodingListenerクラスの作成

まずはイベントリスナークラスを作成します。Symfony本体のFrameworkBundleやHttpKernelコンポーネントのディレクトリ構造の慣習に従ってAcme\DemoBundleの下にEventListenerディレクトリを作成し、その下にイベントリスナークラスを作成します。以下のようなMobileEncodingListnerクラスを作成してください。まだ中身は実装しません。

php:
  1. <?php
  2.  
  3. namespace Acme\DemoBundle\EventListener;
  4.  
  5. /**
  6.  * Convert input encoding or output encoding.
  7.  * @author uechoco <uechoco at gmail.com>
  8.  *
  9.  */
  10. class MobileEncodingListener
  11. {
  12. }

kernel.responseイベント

まずは簡単なkernel.responseイベントに対するメソッドを記述します。クラスの使用宣言を追加して、MobileEncodingListenerクラスにonKernelResponse()メソッドを実装します。

php:
  1. use Symfony\Component\HttpKernel\Event\FilterResponseEvent;
  2. use Symfony\Component\HttpKernel\HttpKernelInterface;

php:
  1. /**
  2.      * Convert output encoding of response.
  3.      * @param FilterResponseEvent $event
  4.      */
  5.     public function onKernelResponse(FilterResponseEvent $event)
  6.     {
  7.         if (HttpKernelInterface::MASTER_REQUEST !== $event->getRequestType()) {
  8.             return;
  9.         }
  10.  
  11.         $response = $event->getResponse();
  12.  
  13.         $response->setContent(mb_convert_encoding($response->getContent(), 'SJIS-win', 'UTF-8'));
  14.     }

中身の処理としては単純で、Resopnseオブジェクトを取得し、その中のコンテンツの文字コードを変換してまたセットしなおしているだけです。今回は説明の簡略化のために文字コードの部分を直書きしています。最初の行のマスターリクエスト以外なら何もしないという条件文がありますが、HttpKernelではリクエストの種別が2種類あり、マスターリクエストとサブリクエストと呼ばれています。そのマスターリクエストの時だけ処理したいので条件式を記述しています。FilterResponseEventクラスを受け取るというのはkernel.responseイベントとの仕様として決められています。

kernel.requestイベント

次にkernel.requestイベントに対するメソッドを記述します。先ほどと同様にクラスの使用宣言を追加して、MobileEncodingListenerクラスにonKernelRequest()メソッドを実装します。

php:
  1. use Symfony\Component\HttpKernel\Event\GetResponseEvent;

php:
  1. /**
  2.      * Convert input encoding of request.
  3.      * @param GetResponseEvent $event
  4.      */
  5.     public function onKernelRequest(GetResponseEvent $event)
  6.     {
  7.         if (HttpKernelInterface::MASTER_REQUEST !== $event->getRequestType()) {
  8.             return;
  9.         }
  10.  
  11.         $request = $event->getRequest();
  12.  
  13.         // GET
  14.         $get = $request->query->all();
  15.         mb_convert_variables('UTF-8', 'SJIS-win', $get);
  16.         $request->query->replace($get);
  17.         // POST
  18.         $post = $request->request->all();
  19.         mb_convert_variables('UTF-8', 'SJIS-win', $post);
  20.         $request->request->replace($post);
  21.     }

こちらもマスターリクエストのみ処理する記述が最初にあります。次にRequestオブジェクトを取得し、今回は$_GETと$_POSTに相当する変数だけを文字コード変換しました。$_GETと$POSTはRequestオブジェクトの$queryと$requestというパブリック変数に代入されています。形式としてはParameterBagというクラスでラッピングされて代入されています。ParameterBagクラスのインターフェースとしてall()メソッドで全配列を取得し、replace()メソッドで全配列を総取替しています。

イベントリスナーとして登録する

最後に、先ほど作ったクラスとメソッドをイベントリスナーとして登録します。登録手順はDIコンテナにサービスとして登録するのと同じですが、特別なタグを定義することでイベントリスナーとして認識されるようになっています。src/Acme/DemoBundle/Resources/config/services.xmlを開き、以下のように追記してください。

XML:
  1. <!-- 省略 -->
  2.  
  3.     <parameters>
  4.         <parameter key="mobile_encoding_listener.class">Acme\DemoBundle\EventListener\MobileEncodingListener</parameter>
  5.     </parameters>
  6.  
  7.     <services>
  8.         <!-- 省略 -->
  9.         <service id="acme.demo.mobile_encoding_listener" class="%mobile_encoding_listener.class%">
  10.             <tag name="kernel.event_listener" event="kernel.request" method="onKernelRequest" />
  11.             <tag name="kernel.event_listener" event="kernel.response" method="onKernelResponse" />
  12.         </service>
  13.     </services>
  14.  
  15.     <!-- 省略 -->

確認する

何事もなければデモ画面が正常に動作すると思います。プロファイラのEvent項を見てみると、リスナーが登録されていることが確認できます。

今回直書きだった文字コードの指定は、config.ymlなどの設定ファイルから取ってくるような仕様にしたり、UserAgentを判別して決定するような仕様にしたほうが汎用性が高いでしょう。

余談

今回の記事の参考にするために他のイベントリスナークラスを見ていましたが、イベントリスナークラスの実装は様々なパターンが存在しているようです。例えば1つのリスナークラスに2つ以上のイベントメソッドをもたせているものや、1クラス1イベントメソッドのもの、他の役割のあるクラスにイベントメソッドを持たせてリスナークラスを兼任させているものなどです。

SymfonyのHttpKernelにどのようなイベントがあるか知りたい方は、Symfonyの内部構造のドキュメントの一節にイベントについて書かれている部分がありますので、そちらを参照してください。

最後に

7日目はMongoDB JPにも所属している@madapajaさんです。よろしくお願いします。


[Symfony2]ブログチュートリアル カスタマイズ編 はじめました

Posted under Symfony2 by uechoco on 月曜日 13 6月 2011 at 13 : 38 : 11


昨日より、Symfony2 ブログチュートリアルのカスタマイズ編の執筆を開始しました

ブログチュートリアルで作ったものにちょっとした修正を加えて、もうちょっとSymfony2の機能を知ってもらおうというセクションです。

現時点で2つのカスタマイズトピックを掲載しています。これから少しずつ執筆していきます。みなさんからのフィードバックをお待ちしています。


[勉強会]第4回Symfony2勉強会に参加&講師しました

Posted under Symfony2 by uechoco on 火曜日 7 6月 2011 at 00 : 34 : 55

2011/6/4(土)に、第4回Symfony2勉強会に参加&講師をしました。この記事では、人前での発表経験の乏しい私が講師という貴重な体験をしたことに対して、経緯や個人的な感想を書こうと思います。

当日のスライド一覧

当日発表のあったすべてのスライドをご覧になりたい方は、他の方がブログでまとめているので、そちらを参照してみてください。

講師をやることになった経緯

もともと、Symfony2の勉強会には、東京で開かれた第1回(2010/11)・第2回(2011/01)に参加していました。これらの勉強会には予習した(事前にドキュメントを見ながらSymfony2のコードを触った)上で参加していったので、参加者の中では結構アグレッシブに追っていた感じでした。第2回はフォーム+Doctrine2のワークショップだったのですが、説明を殆ど聞かずにワークショップの課題を完成させていました。また予習の成果があったので、(人生初の)LTを突発でやったりもしました。

本来正式版がリリースされるはずだった3月5日をすぎ、4月に入りました。@hidenorigotoさんから、しばらく間があいたから6月はじめに東京で勉強会を開こうという話が上がり、メーリングリストで基礎編ワークショップと講演・LTの2部構成の提案がなされました。その数日後、@hidenorigotoさんからTwitterで講師のお誘いを受けました

とまぁ、一瞬躊躇したものの、結局やることになりましたw 第2部の実践的な講演のためのいいネタをもってそうな人以外で基礎的な部分をある程度理解している人という感じでお誘いを受けたんでしょうか?

かくして、5分のLTを1回くらいしか経験したことのない私が、2時間近いのワークショップを担当することになりましたww

資料をつくりはじめる前にしたこと

資料を作り始める前に、人前で話すことについて学べる本や、プレゼン資料を作るための本をあさって、以下の3冊を読みました。

この3冊はどれもオススメです。

『パブリックスピーカーの告白』からは、スライド作成にかける時間の考え方、事前練習の重要性、当日準備の重要性などが特に役立ちました。
『プレゼンがうまい人の「図解思考」の技術』からは、つまらなくないプレゼントはなにか、聞き手が何を求めているのか、どういう風にプレゼンのフレームを組み立てていくかを学びました。
『わかりやすく伝える技術』は前述の本の参考資料だったので読んでみました。この本からは、3のマジック、伝えたいことの順番の考え方、気をつけるべき日本語を学びました。

これらの本を読まなかったら、スライドや当日の発表は悲惨なことになっていたのではないかと思います。それくらい、今回のスライド・発表は影響を受けています。

スライドの作成

今回は、ATNDの説明に、どういったことをやるのかを事前に書いてもらっていました。この内容は第3回のSymfony2勉強会で@hidenorigotoさんが行ったワークショップと似たような内容でした。スライドの構成として概要説明編とワークショップ編の2つに分けるのは決めていたので、ワークショップ編は第3回のワークショップの内容を参考にしました。

5月のGWが明けても思うようにはスライド作成は進みませんでした。Symfony2は急ピッチで様々な改変が加えられ続けているので、私が第2回で学んだ時よりは設定などの書き方が変わっていたりしました。今のSymfony2の状況に私の知識が追いついていなかったのです。

そんなこんなで、ある時、Symfonyしゃべりば on Ustreamを聞いていた時、@cakephperさんがSymfony2を学んでいたのですが、「CakePHPみたいなブログチュートリアルくらいのライトなサンプルがほしい」という発言をしていたのを聞いて、スライドそっちのけで「やろう!」と思い立ちました。様々なドキュメントを読みつつ、Symfony2を学びつつ、10日くらいで書き上げました。5月の終わりには日本Symfonyユーザー会のWebページにて、公開されました。

結果的には、ブログチュートリアルの執筆を通じて様々なドキュメントを見たことで、一気に知識が増えました。スライド作成もかなりはかどるようになりました。

せっかくなので、スライド作成が進まなかった頃の手書きのスライド原稿をアップしちゃいます。(symfony2_ws4_handout_before)最終的に作られたスライドとは構成が全然違いますねw

出来上がったスライドはこちらです。

練習

先述した『パブリックスピーカーの告白』では、練習が非常に大事であることが書かれています(にもかかわらず、多く人は練習をしていなくて、あまり良質ではない講演をしているとも)。私は勉強会の前日に有給をとって、家で練習を2回しました。2時間近いの講演なので、1回練習すると、2時間かかりますw 結構しんどいです。

プレゼンのための練習は今までしたことなかったんですが、練習すると、自信がもてます。実際にスライドを動かして説明してみないと気づかないようなスライドの不自然なところとかが見つかります。練習はしたほうがいいです。すべきです。

当日

そんなこんなで、発表当日になり、発表をしました。

3時間の枠で、前後に会場説明と締めの挨拶、真ん中の1時間は昼休憩でした。昼休憩前までは、概要説明をして、ワークショップの冒頭に進めたので、練習通りにいいペースで進んでいるなと思っていました。もしかしたら、ワークショップ編も速く終わっちゃうんじゃないかとも思っていました。

でもそんなことはありませんでした。休憩後、ワークショップを続けていると、スライド中のコードを参加者が写経する時間が思った以上に長いと気づきました。幾つかの深い階層のファイルを編集しつつ、多くのコードを書きつつで、なかなか写し終わらなかったのです。これは練習では気付かなかった誤算でした。説明し切れるぎりぎりの時間まで手を動かしてもらって、結局最後の残り10分はどうしても伝えたかった残りのスライドの要点を説明するだけの次官になってしまいました。それでもなんとか全部のスライドを説明することは出来ました。

振り返り

後から気づいたのは「コードを配布する」ほうがよさそうだということです。私の勝手な思い込みで、説明をしっかり聞きながら順々に進めていけるようにコードの配布はしなかったんですが、コード配っても聞きたい人は説明聞くだろうし、先に進めたい人はどんどん先に進むんだろうなって思いました。これは次に何か機会があれば活かしたいと思います。

しゃべりのほうは、録音したものを聞いてはいないのでよくわかりません。決して良かったとは思っていません。昔からしゃべることが苦手でしたので、聞きづらかったんじゃないかなっと思っています。

最後に

社会に出てまだ2年目に入ったばかりの人間(私)にとって、大人数の前で長い時間講師をするという経験は、なかなかないんじゃないかと思っています。こういう経験をできたこと・機会をもらえたことに感謝しています。またもっと人に教えるという技術を磨きたいなーと率直に思いました。

この記事が、誰かのお役に立てることを願います。みんなも発表とか講師とか、やろうZE☆!

追伸(2011/06/07 00:57): そういえば、立って話しているとき、実は足震えてましたww(マジで




[Symfony2]ブログチュートリアルを執筆しました

Posted under Symfony2 by uechoco on 月曜日 30 5月 2011 at 23 : 24 : 30

数日前のことですが、Symfony2をスムーズに学んでいただくためのライトなサンプルとして、ブログチュートリアルを執筆いたしました。

以前より日本Symfonyユーザー会では、symfony 1.x系のためのブログチュートリアルを公開していました。symfony 1.x系にはJobeetという素晴らしい実践サンプルがあります。しかしながらこのJobeetはまる1ヶ月を要して作り上げていく実践サンプルになっていて、入門するには非常に敷居が高いものでした。そこで日本Symfonyユーザー会では、CakePHPのマニュアルを参考に独自のコンテンツとしてブログチュートリアルを書き上げました。

今回、同じブログチュートリアルのSymfony2版が出来上がったことで、Symfony2の基礎知識を学ぶための入り口が1つ増えました。ブログチュートリアルを通じて、コントローラ・ルーティング・データベース・フォーム・バリデーション・テンプレートなどの基礎知識が学べます。同時に、CakePHPやsymfony 1.x系のブログチュートリアルと比較をすることで、各フレームワークでの作り方の違いを学ぶことができると思います。

Symfony2の世界は広大でとても奥が深いので、闇雲に学ぼうとすると迷宮に迷いこんでしまいます。まずはブログチュートリアルを読んで、基本的な知識を身につけてみてください。

blogチュートリアル | Symfony2 Blog チュートリアル


[Symfony2]第4回Symfony2勉強会で講師をします

Posted under Symfony2 by uechoco on 月曜日 30 5月 2011 at 23 : 07 : 01

2011/6/4(土)の第4回Symfony2勉強会にて、基礎編ワークショップの講師をすることになりました。

基礎編ワークショップではSymfony2の概要を知ってもらい、実際に手を動かしてSymfony2に触れてもらいます。基礎編ですので難易度の高いDoctrin2やForm周りは避けて、バンドルの作成とTwigの使い方など、初歩的な内容になっています。

当日はUstreamの上映もありますので、楽しみにしてください。

ちなみに、こういった勉強会での発表経験といえば、5分のLTが1回だけしかなく、講師という役回りも人生初でして、とてもとても緊張しておりますww


次ページへ »

Copyright © 2012 うえちょこ@ぼろぐ. WP Theme created by Web Top.