スポンサーサイト

0

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


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

    [バッドノウハウ]Symfony2で別テーブルの集計項目を一覧に含めたいとき

    0
      タイトルが日本語でおk状態ですが…。
      [支店]にoneToManyで結びつく[売上]があるシステムで「支店一覧画面に、各支店の今月の売り上げ表示してよ」という類の要望が来たときとイメージしてくださいwww

      symfony1+doctrine1なら簡単です。[支店]モデルに下記のようなメソッドを足して、
      public function getMonthlyAmount($year, $month)
      {
        return Doctrine::getTable('売上')->getMonthlyAmount($this->getId(), $year, $month);
      }
      支店一覧テンプレートの各行で下記のように呼び出せばいい。
      <?php foreach ($pager->getResults() as $branch): ?>
          <tr>
            <td><?php echo $branch->getName(); ?></td>
            //略…ここに支店の所在地とか電話番号とか
            <td><?php echo $branch->getMonthlyAmount(); ?></td>
            //略…ここに編集ボタンとか詳細ボタンとか削除ボタン辺り。
          </tr>
      <?php endforeach; ?>


      しかし、この手段はSymfony2+Doctrine2では取れません。
      [支店]エンティティのメソッドからはエンティティマネージャや他のエンティティのレポジトリを呼び出すことができず、売上テーブルへの集計SQLを発行できないからです。
      ※mappingの書き方次第では全部の売り上げのArrayCollectionなら持ってたりしますけど、一々全ての[売上]をforeachでループ廻して集計するのは現実的じゃないので却下しますw

      さて、どうするか。
      doctrineのイベント使ったら、[支店]エンティティからメソッド呼び出したタイミングで[売上]に対する集計ができたりするのかな?
      コントローラ側でSQL発行するときにDBテーブルにない項目含めてもエンティティが取りだせたっけ?
      ブログチュートリアルやったレベルのビギナーはここで完全に途方に暮れます(’・ω・`)
      いっそsymfony1にフレームワークを変更しようか…まで考えます。

      ところがどっこい、Symfony2をとことん勉強しないと不可能に思えた、各行ごとに別テーブル(同じテーブルに対してでもいいですが)からのデータを取り出す裏ワザ、TwigExtensionを使うと実現できちゃうんです。
      カスタムTwig拡張の書き方(まだユーザー会翻訳がなくて英語版のみ)
      http://symfony.com/doc/master/cookbook/templating/twig_extension.html

      以下、簡単な書き方サンプル(タイプヒントとかちゃんと書いてない悪い例ですよ〜)

      namespace My¥CoolBundle¥Twig¥Extension;

      class BadKnowHowExtension extends ¥Twig_Extension
      {
          private $em;

          public function __construct($doctrine)
          {
              $this->em = $doctrine->getEntityManager();
          }

          public function getName()
          {
              //他と被らなければ何を入れてもOK
              return 'bad_knowhow';
          }

          public function getFunctions()
          {
              return array(
                  'monthly_uriage' => new ¥Twig_Function_Method($this, 'calculateMonthlyAmount'),
              );
          }

          public function calculateMonthlyAmount($branch, $year, $month)
         {
              return $em->getRepository('MyCoolBundle:売上')->calculateMonthlyAmountForBranch($branch->getId(), $year, $month);
          }
      }
      #My/CoolBundle/Resources/config/services.yml
      services:
          my.cool_bundle.twig.bad_knowhow_extension:
              class: My¥CoolBundle¥Twig¥Extension¥BadKnowHowExtension
              arguments:
                  - @doctrine
              tags:
                  - { name: twig.extension }

      ポイントはservices.ymlで自作のTwigExtensionを登録するときにargumentsとして@doctrineを入れておくこと。
      これで自作TwigExtensionのコンストラクタでentityManagerを取得することができ、好き勝手にSQLを発行させることができます。Ψ(`∀´)Ψ

      あとはtwig側から呼び出すだけ!
      {% for branch in list %}
        <tr>
          <td>{{ branch.name }}</td>
          //略
          <td>{{ monthly_uriage(branch, year, month) }}</td>
          //略
        </tr>
      {% endfor %}


      #ホントのホントにバッドノウハウもいいところですが、これを読んだら「そんな酷い書き方しちゃいかん」とユーザー会のすごい人たちが出てきて正しい方法を教えてくれるかもしれない、という期待を込めて書いてみた(キリッ


      Symfony2のsecurityでハマった結果少しだけわかったこと(メモ)

      0
        Symfony¥Bundle¥SecurityBundleを使ってログイン機構を作っているときに、ログイン状態を手動で変更したいことってありますよね!(いきなり力説

        通常はlogin_checkにpostすればいいのですが、ログインするかどうかは任意でログインすれば特典あり、という仕様の時(ECサイトとかECサイトとかECサイトとか)に、どうやって実装するか考えると、方法は二通りあると思います。
        *ログイン希望する/しないを選択するUI(ボタンだったり、ラジオボタンだったり)をトリガーにしてjavascriptで移動先を変える。
        *POSTを受け取ってからログイン希望の場合はログイン、ログイン希望しない場合はログインしないまま処理を続行する。

        このうち、通常のログインアクション外でのログイン状態変更が必要になるのは、後者の実装を選択したケースです。

        通常のアクション内で手動でログインを行うには、下記のようなコードを書けば良いようです。
        // Get the security firewall name, login
        $providerKey = $this->container->getParameter('fos_user.firewall_name');
        $token = new UsernamePasswordToken($user, $password, $providerKey, $user->getRoles());
        $this->get("security.context")->setToken($token);

        // Fire the login event
        $event = new InteractiveLoginEvent($this->getRequest(), $token);
        $this->get("event_dispatcher")->dispatch("security.interactive_login", $event);

        引用元:http://stackoverflow.com/questions/10422251/manual-authentication-check-symfony-2

        一つだけ注意しなければいけないのは、Symfony¥Component¥Core¥Authentication¥Token¥UsernamePasswordTokenのソースにも、上記のコードにも$providerKeyという名前で示されている変数が、security.ymlに記載したprovidersのほうにつけた名前ではなくfirewallのほうにつけた名前だということです。(上記コードのコメントにもfirewall nameと書いてくれていますね)

        ここを間違えると、コード正しく書いたはずなのにいつまで経ってもログイン状態が変更できない…と延々悩むことになりますので注意です。
        以上、私が不注意で無駄にハマったという経験談の披露でしたorz


        1

        PR

        calendar

        S M T W T F S
             12
        3456789
        10111213141516
        17181920212223
        2425262728  
        << February 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