TwigからEntity::findするフィルターを書いてみた (Symfony Advent Calendar JP 2011 2日目)

初日の @brtriver さんに引き続き Symfony Advent Calendar JP 2011 の2日目です。


ここ数ヶ月 Symfony2 を触っています。実は Symfony 1.X の頃は興味ありながらもほとんど触っていなくて、2になってから触り始めたビギナー&ニューカマーなんです。諸先輩方よろしくお願いします。

Symfony Advent Calendar JP 2011ができるまで

昨年はSymfony Advent 2010をやっているのは知ってたので、今年はどうするのかなーやらないのかなー? と思って

とつぶやいたら、さっそく@ さんからリプライがあって、という流れで、何故か新人なのに取りまとめ役をやることになりました。不用意につぶやくと話が転がって面白い事になるという良い例です(笑)

Twig フィルターを書いてみた

プロパティの動的参照

さて本題です。Symfony2 の標準テンプレートエンジンの位置にある Twig ですが、開発しているのが Symfony の作者である Fabien さんだけあって、View としての役割がきっちり守られていて、余計なことはできないようになっています。


例えばオブジェクトのプロパティを動的に取得するようなことも、現在 Symfony2 にバンドルされている Twig 1.1.2 ではできません。Github Issues で話題になった時も Fabien は

This feature won't be included in Twig. Twig is a template system, not a fully-features language. Dynamic properties is clearly out of Twig scope.
訳: それは Twig の機能として含まれるべきではないよ。Twig はただのテンプレートシステムでフル機能の言語じゃないんだ。動的なプロパティ参照は Twig のスコープ外だよ。

https://github.com/fabpot/Twig/issues/41

と答えています。(その後考え直したのか Twig 1.2 から attribute 関数が導入されて、オブジェクトのプロパティを動的に取得できるようになりました。)

Entityから動的に取得する Twig フィルター

さて今回作成した Twig Filter は、Entity に対して検索をして値を取得するという、上記をさらに一歩踏み越えたある種のキワモノです。ロジックは Model や Controller でという原則からは外れるので安易に使うべきではありません。とは言えそういうキワモノを作るにはそれなりの理由もあるのです。

たとえばユーザの属性情報を考えてみましょう。ユーザはたくさんの属性情報を持っている場合があります。そのたくさんの属性のうちどれをどうやって表示するかを決めるのは View ですが、それを実際に表示するには Model や Controller 側でお膳立てをしておく必要があります。あるアイテムの所有者としてユーザ情報を表示するときに、そのユーザ情報の種類がすごく多かったり、直接 JOIN できなかったりする場合、M/C 側で全てを準備することは逆に現実的ではないと思うのです。

Symfony2 で Twig Extension

ということで、こんな Twig フィルターを作りました。

<?php
namespace Koyhoge\HogeBundle\Twig;
class HogeExtension extends \Twig_Extension {
    public function getFilters() {
        return array(
            'entity' => new \Twig_Filter_Method($this, 'entityFilter'),
            );
    }
    public function entityFilter($entity, $id, $prop, $by = null) {
        if (empty($by)) {
            $obj = $entity->find($id);
        } else {
            $objs = $entity->findBy(array($by => $id));
            $obj = $objs[0];
        }
        if ($obj == null) {
            return '';
        }
        $method = 'get' . ucfirst($prop);
        $call = array($obj, $method);
        if (!is_callable($call)) {
            throw new \Exception('Not callable:' . $method);
        }
        return call_user_func($call);
    }
    public function getName() {
        return 'hoge';
    }
}
使い方:Controller 側

Controller 側で以下のように Entity を直接 Twig に渡します。

<?php
namespace Koyhoge\HogeBundle\Controller;
use Symfony\Bundle\FrameworkBundle\Controller\Controller;

class DefaultController extends Controller {
    public function indexAction() {
        $users = $this->getDoctrine()->getRepository('KoyhogeHogeBundle:User');
        $items = array(
            array('user_id' => 1),
            array('user_id' => 11),
        );
        return $this->render('KoyhogeHogeBundle:Default:index.html.twig',
                             array('users' => $users', 'items' => $items));
    }
}
使い方:Twig テンプレート側

テンプレート側では以下のように呼び出せます。

{% for item in items %}
  {{ users|entity(item.user_id, 'name') }}
{% endfor %}

{{ users|entity(item.user_id, 'name') }}

の部分で、User Entityから item.user_id で find() を行い、その結果のオブジェクトから name プロパティを取得する、という処理を行います。

他のキーで findBy()

別のユニークキーで findBy() したい場合は

{{ users|entity(item.other_id, 'name', 'other_key') }}

などのように3番目の引数に渡します。

まとめ

正直あまり実用的ではない tips ですが、View に必要なデータを Controller 側ですべてお膳立てするのはなんか違うなーと感じていたので、試しに実装して見ました。何にでも多用することは危険だと思われますが、デザインの都合によっていつ表示するか分からない基本的な情報をこのやり方で処理するのは、有効なのではないかと思っています。


明日は、今回の Advent Calendar 企画を私に振った張本人、日本の Symfony 界の重鎮 @hidenorigoto さんです。よろしくお願いします!

そろそろPHPMatsuriについて書いておくか

http://www.flickr.com/photos/zatsu/6260016709/
Photo CC by @


PHPMatsuri については「闇」で発表したスライドの記事を書いたのでそれでいいかとも思ってたんだけど、いやもっとちゃんとブログを書こうと思い直したばかりだったし、せっかくだからもう少し書いておきます。


大阪入りする前から今回の PHPMatsuri で何をするか考えていても何も浮かばなくて、実際にイベントが始まって一応とあるライブラリの extension を作ろうかと思いついたのだけど、さすがに準備が全然できてないので VirtualBoxCentOS 6.0 x86-64をインストールして環境をほげほげしてたら時間切れになってしまった。


まあそれでも、仕事で悩んでた Symfony2 の Bundle の設計について明確な回答をもらえたり、闇PHPMatsuri で Net_IPv6 に送ったパッチの発表をしたり、光画部活動でたくさん写真を撮ったりで、楽しかったし得るものもそれなりにありました。


TDD や CI など今日びの開発手法を多くの人達が使いこなしているのを見て、自分も負けてられないなぁと思いました。PHP は Web 開発業界では底辺に見られがちだけど、開発効率や信頼性を高めるべく新しい技術を貪欲に取り入れる人達もたくさんいます。PHP の言語仕様がダメダメな部分は分かった上で、素晴らしい設計をしたり素早く素晴らしいコードを書くことはできるし、それらを広めることで下らない苦労をする人が一人でも減れば PHP の可能性をもっと広げることにもなるのだと思います。


参加者はすでに日常に戻り日々のコードとの戦いに復帰しているのだと思われますが、年に一回くらいはああいう特別な場所で、熱い想いを持っている人達の空気にどっぷり浸かるのも、エンジニアとしてしての生き方には必要なのだろうと思います。


そう、終わってみて分かる。あれは「特別な場所」でした。来年の開催はまだ不明ですが、今年いろんな理由で参加を躊躇した人は一度は参加してみることを強くお薦めします。

2日目午前中の光画部活動

@ の「今年も撮影散歩行こうよー」という一言で、PHPMatsuri 会場の国際交流センターから、インテック大阪の横を通り、ATC まで撮影しながらぐるっと歩きました。


南港の辺りは埋立地ということもあって、どうしても風景がお台場とかぶりますね。今回の見た中にはすでに廃墟になりかけている建物もあったりして、10年後のお台場もひょっとしてこんな感じなのだろうかと感傷にふけれます。

http://www.flickr.com/photos/koyhoge/6249835479/in/set-72157627906825886
廃墟なりかけその1

http://www.flickr.com/photos/koyhoge/6250299669/in/set-72157627906825886
廃墟なりかけその2

その他の写真はこちらから。
20111016-osaka - an album on Flickr

帰京途中に寄った大阪駅ビルからの夜景がすごかった

http://www.flickr.com/photos/koyhoge/6253963357/in/set-72157627794038827

帰りは @ @ と一緒に帰ることになったのですが、二人とも新しい大阪駅の駅ビルをまだ見てないというので、ちょっと寄り道してノースゲートビルディングを観光してきました。
自分が前回来たときには大雨で見ることができなかった屋上農園も、今回はばっちり見学できました。

http://www.flickr.com/photos/koyhoge/6254519012/in/set-72157627794038827


前回はまだ骨組みだけだった駅北側のビル群も、今回見たらずいぶんと出来ていて、なんかもう物凄くなりそうな予感が今からプンプンします。楽しみ。


その他の写真はこちらから。
20111016-Osaka Station - an album on Flickr

闇PHPMatsuriで発表した

最初はネタ無いしなーと思ってたけど、Net_IPv6 に送ったパッチの話は Twitter にしか書いてなかったので、さくっとスライド作って発表した。

Slideshare は .key を直接アップロードできるようになったのは良いけど、font matrix がずれるみたいすね。

秋にはプログラム言語イベントの大トリに行くのだ

みなさんはもうとっくにご存知ですよね。再来週末にとてもエキサイティングなプログラム言語イベントが開催されます。

  • 2日間に渡る濃いセッションの数々
  • 国内外のハッカー達が多数集まる
  • 海外ゲストも参加

ここ数年は初夏から秋にかけて、プログラム言語系の大きなイベントがいくつか開催されていて、毎年楽しみな恒例行事となっています。LL イベントや RubyKaigi もそうですし、先日開催された PHP カンファレンスもその一つですね。PyCon JP はまだ参加したことはないですが、いつか参加したいと思ってます。そして今年もまたアレが開催されます。そう! YAPC::Asia Tokyo 2011 が!



えー、このエントリは PHPMatsuri リレーブログの4日目なので PHPMatsuri の事を書こうと思っていたのですが、同じキーワードがいくつかあったのでネタに走ってしまいました。


でも実際に YAPC::Asia Tokyo 2011 は、10/13(前夜祭), 10/14, 10/15 に開催されますし、前夜祭と1日目は私も参加するつもりで 1日券のチケットを購入済です。そして YAPC::Asia の2日目に後ろ髪をひかれながら大阪に移動して PHPMatsuri 2011 に参加する予定です。


予算的にちょっと辛いかもという話を聞いていたので、今回は我らがほげ技研もシルバースポンサーとして協賛させて頂いてます。


昨年の PHPMaturi 2010 では、自作の DB ライブラリの依存部分を整理して Keires_DB として openpear でリリースしたり、写真をたくさん撮ったり、会場近所の中央清掃工場の大煙突が激烈にかっこよくて感動したり、色んな人と話したりしました。100人近くの人が集まるハッカソンだけに、楽しみ方はひとそれぞれでそれも面白かったです。

さて今年の PHPMatsuri 2011、一泊4食で22,000円。確かに安くはないですが、もし参加しようかどうしようか迷っている人がいたら、他の技術イベントではなかなか経験できない貴重な機会がそこにあることをお伝えしておきます。合宿ハッカソンをまだ経験したことがないなら、一度は経験してみることをお勧めします。

さて、リレーブログ。明日は @tanakahisateru さんです。

「FlexでTitleWindowをresize可能に」へのパッチ

Flex でちょっと凝ったモーダルダイアログを作りたいときに便利な TitleWindow をリサイズ可能にしようと思って調べたら、以下のエントリを発見しました。

Flex で TitleWindow を resize 可能にする - Enjoi Blog

おおまさにこれだと、とても便利に使わせていただいたのですが、TitleWindow の子要素によっては意図せずしてリサイズ処理に入ってしまうことがありました。


これは子要素に対して発生したイベントが、バブリングで TitleWindow に届いたときに起こります。その時の event.localX, event.localY は子要素の座標系での値になりますので、それをリサイズ開始の判断に用いるとおかしなことになるんですね。

ということで onThis_mouseDown メソッドを以下のように修正しました。ステージ座標系の値から計算して、TitleWindow でのマウス座標を求めています。

      private function onThis_mouseDown(event:MouseEvent):void
      {
        var stageX:Number = event.stageX;
        var stageY:Number = event.stageY;
        var ctX:Number = event.currentTarget.x;
        var ctY:Number = event.currentTarget.y;

        var loc:Object = {
            x: stageX - ctX,
            y: stageY - ctY
        };

        // check Top pos
        if( loc.y < SIZE_DRAGAREA )
        {
          blDragTop = true;
          iDragPosHeight = loc.y;
        }

        // check Right pos
        if( this.width - SIZE_DRAGAREA < loc.x )
        {
          blDragRight = true;
          iDragPosWidth = this.width - loc.x;
        }

        // check Bottom pos
        if( this.height - SIZE_DRAGAREA < loc.y )
        {
          blDragBottom = true;
          iDragPosHeight = this.height - loc.y;
        }
        
        // check Left pos
        if( loc.x < SIZE_DRAGAREA )
        {
          blDragLeft = true;
          iDragPosWidth = loc.x;
        }
      }

GOOD DESIGN EXPO 2011

http://www.flickr.com/photos/koyhoge/6085260097/

昨年はRubyKaigiにぶつかっていて悔しい思いをした「GOOD DESIGN EXPO 2011」を、今年はばっちり見学してきました。


振り返れば GOOD DESIGN EXPO に最初に行ったのは2008年で、一度行ってその魅力にメロメロにやられてしまった訳です。ちょうどα350を手に入れたタイミングだったので、写真撮りまくりっぷりが flickr の set に残っています。

良いデザインはアイディアの宝庫

言うまでもなく、良いデザインは何らかの問題を解決するために脳みそを絞り尽くした知恵の抽出物です。そんなアイディアがガンガン詰まった数々のデザイン製品が死ぬほど集まっているのですから、これが面白く無い訳がありません。


GOOD DESIGN EXPOは、原則的にすべての出品物は実際に可動状態で手に取って触ることができる、おそろしい程におおらかで、言い換えれば見学者を信頼している展示会です。「神は細部に宿る」と言うように、実際に触った質感や細かい作りこみから感じることや、近くから見るだけでは分からないことも数多くあります。この展示会は、一部の例外を除いて多くの製品をじっくり触り倒すことができる素晴らしく貴重な機会です。数多く触っているうちに、デザインを生み出した意識の流れに飲み込まれ奔流される感覚さえ感じます。これが病みつきになるんですねw


13時頃に入場したのですが、20時過ぎまでほぼ休みなしノンストップで歩きまわり、触りまくってました。あっという間に時間が経つんだよなぁ。

続きを読む