スポンサーサイト

0

    一定期間更新がないため広告を表示しています


    • 2014.12.23 Tuesday
    • -
    • -
    • -
    • -
    • -
    • by スポンサードリンク

    Symfony2のControllerで@Templateを使うメリット

    0
      仕事が忙しくて予定してた実験ができなかったので小ネタ。

      symfony1.xに馴れた身でSymfony2を触ると、色々面倒なことってありますよね。
      例えば、sfDoctrineRoute。例えば、テンプレート名とアクション名が同じならわざわざ指定しなくていい。

      明示的で後から参加する人にもわかりやすくなったのは良いんですが、裏を返せばエキスパートにとってはわかりにくくなったと思うんです。(言いすぎ)

      symfony1.xの便利機能が恋しい〜。
      ところで、それ、Sensio¥Bundle¥FramewordExtraBundleにほとんどあります。

      Sensio¥Bundle¥FrameworkExtraBundle¥Configuration¥ParamConverter

      sfDoctrineRouteみたいなもんです。
      コントローラのアクションのメソッドにアノテーションにして使います。
      使い方はこの辺り
      一々$this->getDoctrine()->getManager()とかめんどくさくてやってられないでしょ。

      Sensio¥Bundle¥FrameworkExtraBundle¥Configuration¥Template

      通常$this->render()なんかで指定するテンプレート名が指定不要になって、更に、アクションのメソッドが配列を返すだけで良くなる設定。
      これをつけておくだけでAcmeDemoBundle:Foo:barコントローラのテンプレートはAcme/DemoBundle/Resources/views/Foo/bar.html.twigになります。
      @Template("AcmeDemoBundle:Foo:baz.html.twig")と書けばAcme/DemoBundle/Resources/views/Foo/baz.html.twigにも変更可。

      で。ここから、特に@Templateを使うと何が良いのかという話。

      @Templateをつけない場合、コントローラのメソッドの返り値はSymfony¥Component¥HttpFoundation¥Responseになります。
      普通のコントローラ作ってるだけなら別にいいのですが、汎用的なコントローラを作って、それを拡張した新しいコントローラを作ろうとした場合に拡張元が普通のアクションだとメソッドの返り値がResponseになってしまい、非常にカスタマイズしにくいです。

      @Templateなしの場合
      // src/Acme/DemoBundle/Controller/BaseController.php
          public function barAction(Request $request)
          {
              //何かの処理
      
              return $this->render('AcmeDemoBundle:Foo:bar.html.twig', 
                  array('name' => $name)
              );
          }
      // src/Acme/DemoBundle/Controller/FooController.php
          public function barAction(Request $request)
          {
              //parent::barAction($request)だとResponseが返って来ちゃうから…
              //何かの処理(BaseController::barAction()と同じ内容コピペ)
              //追加の処理(カスタマイズ)
      
              return $this->render('AcmeDemoBundle:Foo:bar.html.twig', 
                  array('name' => $name, 'tel' => $tel)
              );
          }
      

      @Templateありの場合
      // src/Acme/DemoBundle/Controller/BaseController.php
          /**
           * @Template()
           */
          public function barAction(Request $request)
          {
              //何かの処理
      
              return array('name' => $name);
          }
      // src/Acme/DemoBundle/Controller/FooController.php
          /**
           * @Template()
           */
          public function barAction(Request $request)
          {
              //返ってくるのは配列だからparent::barAction()使ってOK
              $vars = parent::barAction($request);
              //追加の処理(カスタマイズ)
              $vars['tel'] = $tel;
      
              return $vars;
          }
      

      テンプレート指定の面倒がなくなるだけじゃないよ!という話でした。


      SonataAdminBundleでフォームや一覧表示を実用的にカスタマイズする方法(初歩編)

      0
        SonataAdminBundleとは、"The missing Symfony2 Admin Generator"というキャッチフレーズの通り、symfony1時代のAdmin Generatorのような機能が使えるバンドルです。
        つまり、いくつか決められた設定をするだけで、管理画面が自動で作られる使えるようになるバンドルというわけです。

        インストール方法・基本的な使い方などはバンドルのドキュメント(本家の英語版@最新,@okaponさんによる日本語翻訳@少し古い?)を見てください。

        さて、このSonataAdminBundle、便利な汎用バンドルにはありがちなことですが、少し変わったことをしようと思うと、工夫が必要になります。
        例えば、顧客の性別データを1=男性,2=女性,3=その他で管理しているとします。
        //src/Acme/DemoBundle/Entity/Customer.php
        class Customer
        {
            /**
             * @var integer
             *
             * @ORM¥Column(name="id", type="integer")
             * @ORM¥Id
             * @ORM¥GeneratedValue(strategy="AUTO")
             */
            private $id;
        
            /**
             * @var string
             *
             * @ORM¥Column(name="name", type="string", length=255)
             */
            private $name;
        
            /**
             * @var integer
             *
             * @ORM¥Column(name="seibetsu", type="integer")
             */
            private $seibetsu;
        }
        

        (この実装が良いかどうかは別として)これを前提として、SonataAdminBundleで通常通りに管理画面設定をすると、下記のようになります。
        // src/Acme/DemoBundle/Admin/CustomerAdmin.php
        
        use Sonata¥AdminBundle¥Admin¥Admin;
        use Sonata¥AdminBundle¥Datagrid¥DatagridMapper;
        use Sonata¥AdminBundle¥Datagrid¥ListMapper;
        use Sonata¥AdminBundle¥Form¥FormMapper;
        
        class CustomerAdmin extends Admin
        {
            protected $baseRouteName = 'admin_customer';
        
            /**
             * @param FormMapper $formMapper
             */
            protected function configureFormFields(FormMapper $formMapper)
            {
                $formMapper
                    ->add('name')
                    ->add('seibetsu')
                ;
            }
        
            /**
             * @param DatagridMapper $datagridMapper
             */
            protected function configureDatagridFilters(DatagridMapper $datagridMapper)
            {
                $datagridMapper
                    ->add('name')
                    ->add('seibetsu')
                ;
            }
        
            /**
             * @param ListMapper $listMapper
             */
            protected function configureListFields(ListMapper $listMapper)
            {
                $listMapper
                    ->addIdentifier('name')
                    ->add('seibetsu')
                ;
            }
        }
        

        フォーム表示
        一覧表示

        フォーム(登録・編集、絞込み)でselect,radioを使えるようにする

        まず、フォームで性別コード(1,2,3)を設定するのをやめたいと思います。
        いくら管理画面とはいえ不親切すぎますし、間違いやすいです。
        selectかradioで、男・女・その他のキャプションを見ながら選べるほうがいいですよね。

        最初に、性別専用のフィールドタイプを作ります。サービスとして登録するところまでやっておきましょう。
        作り方はこちら→カスタムフォームフィールドタイプの作成方法(日本語版)
        ※昨日翻訳を更新しておいたので最新版になってます!

        上記ドキュメントではm=Male,f=Femaleになっていますが、1=男,2=女,3=その他で作ります^^;
        フィールドタイプを作り終わったら、CustomerAdmin::configureFormFields()とCustomerAdmin::configureDatagridFilters()でseibetsuをaddするときに、第二引数として専用フィールドタイプのサービス名、つまりgenderを指定します。
            /**
             * @param FormMapper $formMapper
             */
            protected function configureFormFields(FormMapper $formMapper)
            {
                $formMapper
                    ->add('name')
                    ->add('seibetsu', 'gender')
                ;
            }
        
            /**
             * @param DatagridMapper $datagridMapper
             */
            protected function configureDatagridFilters(DatagridMapper $datagridMapper)
            {
                $datagridMapper
                    ->add('name')
                    ->add('seibetsu', 'gender')
                ;
            }
        

        これで、フォーム上の性別のウィジェットが性別選択専用のカスタムフィールドに変わりました。簡単でしたね:)
        変更後のフォーム表示

        一覧上で生の値でなくキャプションを表示させる

        フォームが直ったのでもう充分な気もしますが、一覧で性別コード(1,2,3)が表示されるのも直したいと思います。
        いくら管理画面とはいえ不親切(以下同文

        今度は、カスタムTwigExtensionを用意します。
        作り方はこちら→カスタムTwig拡張の書き方(日本語版)
        ※昨日翻訳したてのほやほやです。

        作るTwig拡張の内容は、【性別コード(1,2,3)を性別のキャプション(男,女,その他)に変換する】という機能をもつ関数にします。
        // src/Acme/DemoBundle/Twig/Extension/GenderNameExtension.php
        class GenderNameExtension extends ¥Twig_Extension
        {
            public function getName()
            {
                return 'acme_demo_gender_name';
            }
        
            public function getFunctions()
            {
                return array(
                    'gender_name' => new ¥Twig_Function_Method($this, 'getGenderName'),
                );
            }
            
            /**
             * @param string $value
             * @return string
             */
            public function getGenderName($value)
            {
                $list = array(
                    1 => '男',
                    2 => '女',
                    3 => 'その他',
                );
                
                return isset($list[$value]) ? $list[$value] : '-';
            }
        }
        
        専用TwigExtensionはサービスとして登録しておきます。
        これで、twigテンプレート側で{{ gender_name(1) }}のような形で呼び出すことで、性別コード→性別キャプションの変換ができるようになりました。

        専用のTwig関数ができたので、ここで、一覧表示の項目用のテンプレートを作ります。
        {# src/Acme/DemoBundle/Resources/views/sonata_customer_list_gender.html.twig #}
        {% extends 'SonataAdminBundle:CRUD:base_list_field.html.twig' %}
        {% block field %}
            {% spaceless %}
                {% if value is empty %}
                     
                {% else %}
                    {{ gender_name(value) }}
                {% endif %}
            {% endspaceless %}
        {% endblock %}
        

        このテンプレートをCustomerAdmin::configureListFields()でseibetsuのテンプレートとして指定したら、完了です。
            /**
             * @param ListMapper $listMapper
             */
            protected function configureListFields(ListMapper $listMapper)
            {
                $listMapper
                    ->addIdentifier('name')
                    ->add('seibetsu', 'string', array(
                            'template' => 'AcmeDemoBundle::sonata_customer_list_gender.html.twig',
                        ))
                ;
            }
        

        性別コードでなく性別キャプションのほうが表示されるようになりました。
        変更後の一覧表示

        実は私もまだ触り始めたばかりですが、SonataAdminBundleはちょっとした設定だけで色々カスタマイズができることがわかりました。現時点では、設定項目を網羅したリファレンス的なドキュメントが不足しているために、カスタマイズができるところがわかりにくいのが欠点かなと思います。
        今後に期待したいところです!


        Symfony2.3でsessionのflashデータの操作方法が変わった件

        0
          先週後半から、最初のLTS版Symfony2.3を早速使っているわけですが、2.2以前に比べて結構たくさん仕様変更があり、慣れたつもりの私でも「あれ?」という事態が発生しています。
          日本語ドキュメントが全部追いつくまでかなり時間がかかると思われる(スミマセンスミマセン)ので、私がハマった部分だけ個別に書いておくことにしました。

          早速ですが、セッションのflashメッセージの件。
          セッションのflashメッセージは、一回限り(セットしたリクエストの次のリクエストまでの間だけ)保存されるセッションデータです。
          主な用途は、postされたデータをサーバー側で処理した際の完了メッセージ等(たぶん)

          (追記:ソースコードを追った結果この変更は2.3でなく2.1からの仕様変更で、2.2までは後方互換で使えていただけということがわかりました。)

          2.2までの書き方

          コントローラでflashメッセージをセットする:
          $this->get('session')->setFlash('notice', '更新しました。');

          twigテンプレートでflashメッセージが存在するかどうか確かめる:
          {% if app.session.hasFlash('data') %}
              {# dataというflashがある場合の処理 #}
          {% else %}
               {# dataというflashがない場合の処理 #}
          {% endif %}

          twigテンプレートでflashメッセージを表示:
          {# hogeというflashを表示 #}
          {{ app.session.flash('hoge') }}

          2.3からの書き方

          コントローラでflashメッセージをセットする:
          $this->get('session')->getFlashBag()->set('notice', '更新しました。');

          twigテンプレートでflashメッセージが存在するかどうか確かめる:
          {% if app.session.flashBag.has('data') %}
               {# dataというflashがある場合の処理 #}
          {% else %}
               {# dataというflashがない場合の処理 #}
          {% endif %}

          twigテンプレートでflashメッセージを表示:
          {# hogeというflashを表示 #}
          {% for flashMessage in app.session.flashBag.get('hoge') %}
               {{ flashMessage }}
          {% endfor %}
          $this->get('session')->getFlashBag()->set('notice', '更新しました。');のように文字列を一つだけセットしてあっても、app.session.flashBag.get('notice')の中身は必ず配列になります。
          一度$this->get('session')->getFlashBag()->set('notice', '更新しました。');としてから$this->get('session')->getFlashBag()->add('notice', 'もう一つ更新しました。');とすると、2つのメッセージを保存できます。
          ただし、$this->get('session')->getFlashBag()->set('notice', '更新しました。');としてから$this->get('session')->getFlashBag()->set('notice', '再度更新しました。');とすると、後でセットしたメッセージのみが保存されます。(addだと追加されるがsetだと上書き)

          #わかりづらくなって、正直言って改悪じゃないの?という気がしないでもないのですが(-_-;)


          PHPカンファレンス関西2013に参加してLTしてきました #phpkansai

          0

            昨日、大阪で開催されたPHPカンファレンス関西2013に参加してきました。

            基調講演

            まず、久保さんの基調講演。

            Pear::Net_UserAgent_Mobileの作者って久保さんだったのですね。多大にお世話になっておきながら知りませんでしたm(_ _)m

            もつれた意図(糸とかけてる?とか不謹慎なこと考えた^p^)をほぐす、それぞれの意図を表すのに適した方法で。そして、これからのプログラムはもつれをなくす方向に進んでいる。示唆に富んだ内容で、出て来たキーワードだけでも一晩ではとても消化しきれてないので、じっくり考えて、これからのコードに生かしたいと思います。

            セッション

            セッション中はずっと4階後方のユーザー会ブースにいて、4階の発表を聞いていました。

            楽天のエンジニア、Graham Weldonさんによるdebugging=自転車 profiling=バイクの例えはなるほどと思いましたし、スライドに時々登場する日本語がかわいくて和み、xhprofのコールグラフは「是非PNE3やSymfonyのプロジェクトで見てみたい!」と思ってしまいました。最適化のタイミングについても、かなり納得。

            多言語パネルディスカッション。メモに一行「ステートレス」と^^;

            後藤さんの発表、関心を分離する。私にとっては普段から触れている内容なのですが、HTMLとCSSという例えは、初めての人にも非常にわかりやすくてよかったと思います!分離のデメリットは道具(IDE)でカバーというのも素敵。

            安藤さんのChefとVagrantは実は今、(主に仕事の都合上で)一番興味があるところでした。というのも、よりによって年度末にかけて連続してハードウェア障害に見舞われて、サーバー構築やり直しという非常事態を短期間に何度も経験するはめになったばかりで。まずは「挫折しねえ」とオススメされていた『入門chef solo』をkindleでポチってみることにします。

            LT

            「まだ技術ブログを始めていないPHPerのあなたへ。」という題でLTをしました。最初は間に合ったらSymfony Componentネタをやりたいと考えていたのですが、朝からのセッションの流れを見ると、特定ライブラリのネタに走らなくて逆に正解だったかもしれません。

            スライドです。

            運がいいのか悪いのか抽選の結果一番手になってしまい、緊張MAXのまま発表したので、声が震えたり早口になったりと、お聞き苦しい所があったと思います。聴いてくださった皆さまありがとうございました。手加減してくださったドラ娘のお二人もありがとうございました…。

            他の方のLT中は一人で脳内反省会をしていたので、あまり真面目に聞いてなかったのですが(スミマセン)、サーバーサイドにSymfony2を使ってるという話がさらりと出てきた時と、Yamlのお話が本題に入ったと思しきところで時間切れになった時が印象に残っています。YamlのLTされた方のスライドが公開されたらじっくり読みに行かないと。

            裏カンファレンス(?)

            4階がセッション会場から懇親会会場にお色直しする間、6階の会場でディスカッションをするというので移動しました。通称裏カンファレンス?

            最初は挙手アンケートだったものの、途中から生々しいお金の話が飛び交うようになって、さすが大阪ww だが、それがいいw

            突発開催&ust中継がなかったからこそ聞けた話も多く、現地に行った醍醐味を実感することができたイベントだったと思います。

            日本Symfonyユーザー会ブース

            ちょっと時系列から外れて開場〜撤収までほぼ一日中居座っていたユーザー会ブースの話。

            「Symfonyって何ですか?」という方から、「symfony1.4でfacebook SDKの認証のやり方がわからない!」と質問しに来て下さった方まで、色々な人に来ていただいて楽しかったです!
            個人的には、「symfony1系は改修案件で何度か触ったことが」という声を結構聞いた気がするので、symfony1系のドキュメントや小規模な勉強会的なものは需要あるかも…などと。

            思いがけないご縁もあり、楽しくお喋りして時間があっという間でした。(馴れ馴れしくてすみません。。)

            しんふぉにゃんステッカーは是非作りましょう。あと、次はステッカー整理用にクリップと輪ゴムを用意して行きたいと思います^^;

            懇親会

            入り口近くのphpmentorsのテーブル(?)でまったりと語ってました。
            他のテーブルに出張はしなかったのですがお話したいと思った方とは大体お話しできて満足。

            日帰りなので、残念ながら懇親会LT1本目が終わって間もなく離脱しました。

             

            名古屋からみると、大阪は東京より断然近いので、また機会があったらぜひ遠征したいと思いました。実行委員の皆様、お疲れ様でした&ありがとうございました!



            1

            PR

            calendar

            S M T W T F S
                  1
            2345678
            9101112131415
            16171819202122
            23242526272829
            30      
            << June 2013 >>

            twitter

            selected entries

            categories

            archives

            recent comment

            • djangoテンプレート上でmodelのメソッドに引数を渡す方法(djangoで出勤簿アプリ試作中♪)
              GavannITサービス-なりとみ
            • 私がそれでも名古屋市に住み続ける理由を6つにまとめてみた!
              bose wireless speaker
            • FastCGIでdjango…400エラー???
              levi's
            • さくらインターネットdjangoが突然500エラー!?(Pythonバージョンアップされてた
              salomon running shoes
            • 私がそれでも名古屋市に住み続ける理由を6つにまとめてみた!
              louboutin shoes
            • FastCGIでdjango…400エラー???
              yeezy boost 350
            • さくらインターネットdjangoが突然500エラー!?(Pythonバージョンアップされてた
              jordan 11
            • Silexでエラーページをカスタマイズする方法 : Symfony Advent Calendar 2011 - day 12
              pandora jewelry
            • django対symfony 日本語メール送信(その1 symfony編)
              nike air vapormax
            • 解決!XREAでCGI版Pythonを使ってdjangoを動かす(人柱?)
              kate spade

            recent trackback

            • HTMLの表(TABLE)のセル(TD)に斜線を引くjavascriptライブラリ slash.js 作っちゃいました
              常山日記
            • django対symfony 日本語メール送信(その1 symfony編)
              CPA-LABテクニカル
            • CodeIgniterでユーザー認証
              されどLAMPな日々
            • 久々にdjangoを最新版にしたらHTMLがエスケープされちゃった!!(解決済み)
              常山日記
            • FastCGIを諦めてmod_pythonを使う。Apacheのアップグレード
              サーバー用語集
            • さくらインターネット、sqlite3でdjango@CGI版を使う際の設定メモ
              常山日記
            • さくらインターネット スタンダードプランでdjango使ってる方、DBは?
              mitszoの日記
            • python多次元リストをsort(並べ替え)する方法?
              mitszoの日記
            • フォームから送信した値とrequest.POSTの挙動($_POST@PHPとの比較)
              Humming Via Kitchen
            • 日本語テキストをtruncate@django(Python全般にも??)
              常山日記

            recommend

            links

            profile

            search this site.

            others

            mobile

            qrcode

            powered

            無料ブログ作成サービス JUGEM