スポンサーサイト

0

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


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

    Doctrine(1.x)でのLEFT OUTER JOIN実現方法

    0
       公式のドキュメント
      http://www.doctrine-project.org/projects/orm/1.2/docs/manual/dql-doctrine-query-language/ja#join%E3%81%AE%E6%A7%8B%E6%96%87:on%E3%82%AD%E3%83%BC%E3%83%AF%E3%83%BC%E3%83%89
      によると、ONキーワードでリレーション条件がカスタム指定できるようなことが書いてありますが、実際には効きませんorz

      試行錯誤の末、無理やりLEFT OUTER JOINぽいことを実行させることができたので忘れないようにメモ。
      実験しながらエラーMSGでググると、symfony公式のフォーラムでも世界各国の方々がLEFT OUTER JOINができないと悩んでいた。

      なんでONを自分で指定したいかと言うとモデルを次のように定義してあるとして、
      Able:
      columns:
      id: { type: integer(1), primary: true }
      Baker:
      columns:
      id: { type: integer(1), primary: true }
      out_class: string(4)
      out_id: integer(1)
      Cat:
      columns:
      id: { type: integer(1) }
      Bakerはout_classの値によりAbleかCatどちらかにJOIN先が変わります。
      なんでこんな変な構造にするか詳細は聞かないでください(笑

      【実験1】
      まず公式のドキュメント通りに。
      $q = Doctrine::getTable("Baker")->createQuery("b")->leftJoin("Able a ON a.id ON b.out_id");
      ⇒...FROM Baker b, Able a...
      ONどこいった??単にFROMにカンマ区切りで入れられると、SQL側でAble.idとBaker.idで勝手にJOINされちゃって都合が悪い。

      【実験2】
      公式ドキュメントにWITHというのも書いてあるので使ってみた。
      $q = Doctrine::getTable("Baker")->createQuery("b")->leftJoin("Able a ON a.id =b.out_id");
      ⇒...FROM Baker b, Able a...
      WITHどこいった??

      【実験3】
      無理を承知でINNER JOINにしてみる。Linux系OSのMySQLで、MyISAMテーブル(=外部キー制約なし)だとBaker.out_idとA.idのINNER JOINとか普通に成立した記憶が。
      $q = Dcotrine::getTable("Baker")->createQuery("b")->innerJoin("Able a ON a.id = b.out_id");
      ⇒エラー。AbleとBakerの間にリレーションが定義されてないとか何とか。まあ当然。


      ここで公式APIドキュメントを読みに行く。
      Doctrine_Query_Abstruct::leftJoin($join, $params=array())
      色々場合分けはあるが、要は最後に $this->dqlQueryPart['from']に 'LEFT JOIN '.$joinをセットする仕組みのよう。
      【実験4】
      とりあえずセットした後にちゃんとセットされているかどうかチェックしてみる。
      $q = Doctrine::getTable("Baker")->createQuery("b")->leftJoin("Able a ON a.id = b.out_id");
      var_dump($q->getDql());
      ⇒FROM Baker b LEFT JOIN Able a ON a.id = b.out_id
      ちゃんとDQLにはセットされていることが確認できた。
      が、$q->getSqlQuery()すると相変わらず FROM Baker b, Able aのみ。どうやらDQLからSQLを生成する時にONが無視されてしまう様子。

      ここでふと思い出した。Pear::DBを使ってSQLを勉強し始めた頃、FROMにテーブルを羅列してWHEREでJOIN条件書いてもほしいデータが取れてたなー。その後SQL実行速度の問題でちゃんとJOINを書くようになったんだけど。
      【実験5】
      だめもとで。
      $q = Doctrine::getTable("Baker")->createQuery("b")->addFrom("Able a")->addWhere("b.out_id = a.id");
      ⇒実験3と同じエラー。でも、$q->getSqlQuery()ではちゃんとSQLが出て来るし、それをコピペしてphpmyadminに実行させたらちゃんと想定通りのデータが出た。

      【実験6】
      実験5ではAbleのデータを入れるコンポーネント(プロパティ)がないよ!って怒られてる気がしてきた。同時にBakerとJOINするAbleまたはCatのデータはBakerに取得用のメソッドを作ってあるのでAbleのデータを最初のSELECTで取らなくてもいいよね、と考える。
      $q = Doctrine::getTable("Baker")->createQuery("b")->addFrom("Able a")->addWhere("b.out_id = a.id")->select("b.*");
      ⇒成功!!

      ここまで来るのに休み休み(家事育児やりながら^^;)で4時間近くかかってしまった(汗
      【結論】
      スマートじゃない&MySQLエンジンがんばって!なSQLだけど、上記の方法でLEFT OUTER JOINっぽいことはできることがわかりました。



      [OpenPNE3.x]op_include_yesnoヘルパーがすごい

      0
         超便利なヘルパーを見つけた(発掘した)ので感動が冷めないうちにまとめておきます。
        何かに書いておかないとまた忘れちゃいそうなのでw

        function op_include_yesno($id, $yesForm, $noForm, $options)
        #定義はopPartsHelper内にあります。

        $id…formを囲むdivに付けたいid名。HTMLのid名なので同一ページ内の他のidと干渉しなければ自由につけられます。例えばスケジュール削除確認の画面ならscheduleDeleteConfirmFormとか。まぁ好みで。

        $yesForm…「はい」の場合に送信するformインスタンス。予めアクション側で作ってビューに渡しておく。⇒私はこのyesnoを主に<削除確認画面>で使ってるので、大抵の場合は単なるsfFormなのですが。何かのパラメータをhiddenで渡したいときにはhiddenFieldsを持ってるformを作って値をセットして渡せばOK。

        $noForm…「いいえ」の場合に送信するformインスタンス。$yesFormと以下同文。

        $options…オプションの連想配列。op_include_formを使ったことがあればほぼ同じオプション内容が使えます。ただし、送信先URLの指定がyes,no2つ分あるのでそれぞれ指定すべし。⇒前述の通り私は<削除確認画面>で使ってるので、yes_urlを削除実行のアクションのURL、no_urlを表示のアクションのURLにしてます。
        yes_url…yesの場合($yesForm)の送信先URL
        no_url…noの場合($noForm)の送信先URL
        title…formを囲むdivのpartsHeading>h3に入るテキスト。無指定だとタイトルなしのブロックになる。⇒<削除確認画面>だと「予定削除の確認」とか。
        body…yes,noボタンの上に表示したいテキスト。⇒<削除確認画面>なら「本当に削除しますか?」とか「削除します。よろしいですか?」とか。
        yes_button…yesのボタンのvalue。「はい」とか「削除する」とか「出席する」とか。デフォルトは「はい」。
        no_button…noのボタンのvalue。「いいえ」とか「中止する」とか「欠席する」とか。デフォルトは「いいえ」

        op_include_formとの違いは、view.ymlによるカスタマイズの読み込み機構は付いてないところぐらい?まぁどうしても必要なら足せばいいけど。


        すごい便利なのにバンドルされてるプラグインでもほとんど使われてないのが不思議。
        皆さんもお試しあれ。


        1

        PR

        calendar

        S M T W T F S
            123
        45678910
        11121314151617
        18192021222324
        25262728293031
        << July 2010 >>

        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