質問をすることでしか得られない、回答やアドバイスがある。

15分調べてもわからないことは、質問しよう!

ただいまの
回答率

90.12%

CakePHPのJOINしたpaginateでのJOIN側の検索ができない。

解決済

回答 1

投稿

  • 評価
  • クリップ 0
  • VIEW 3,847

asibarcom

score 5

表題の件で、いろいろな文言でググっても解決策がわからず・・・ 助けてください。 

AAAテーブルにLEFT JOINにてBBBテーブルを結合し、BBB内を検索したいのですが、
現状では、AAAしか検索できません。
DebugKitでSQLログを見ると、AAAテーブルをLIMIT検索し、AAA.IDをもとに、BBBテーブルをWHERE INにて検索してるみたいです。それなので、BBB側を検索するとそもそもそんなカラムはないとエラーになります。
なので、$paginateのコメントアウトしてる'join'を追加すると・・・
検索はできるのですが。paginateのカウント処理でLEFT JOINが同じBBBを2回行いSQLエラーになります。

モデル側

class AmznGiftCode extends AppModel {
        public $hasOne = array('AmznGiftCodeUse');
}

 

コントローラー

class xxxxxController extends AppController {

    var $uses = array('AAA',"BBB");

    //読み込むコンポーネントの指定
    public $components = array('Paginator');

    public $paginate = array(
        'limit' => 50,
        'maxLimit' => 1000,
        'order' => array(
            'AmznGiftCode.id' => 'asc'
        ),
        'group'=>"AmznGiftCode.id",
        'paramType' => 'querystring'
        // ,'joins' => array(
        //     array(
        //         'type' => 'LEFT',
        //         'table' => 'bb_bb_bb',
        //         'alias' => 'BBB',
        //         'conditions' => 'BBB.aaa_id = AAA.id'
        //     )
        // )
    );
〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜
public function index(){
      $this->AAA->unbindModel(array('hasOne' => array('BBB')));
      $this->AAA->bindModel(array('hasMany' => array('BBB'=> array('order' => 'id DESC'))),true);
〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜  

      $conditions = array();
      if(isset($this->params['url']['text']) && !empty($this->params['url']['text'])){
        //Formの値を取得
        $text = $this->params['url']['text'];
        //検索文字を空白(全角又は半角)で区切って配列$keywordsに代入
        $keywords = preg_split("/ |\s/",$text);
        //配列$keywordsの数だけ繰り返して検索条件を$conditionsに代入
        foreach($keywords as $keyword){
**AAA.claim_codeは検索できるけど、BBB.emailが検索できない**  
           $conditions[] = "`AAA`.`claim_code` like '%$keyword%' OR `BBB`.`email` like '%$keyword%'";
        }
        $search_condition['text'] = $text;
      }

      //ページングパラメーター設置
      $this->Paginator->settings = $this->paginate;

      $data = $this->Paginator->paginate('AAA',$conditions);
      $this->set('AAAView', $data);

この情報だけで分かりますか?必要情報あれ追記いたします。

お分かりになる方よろしくお願いします。
お力添えをお願いいたします。

ーー 環境情報 ーー 
CAKE_VERSION:2.7.5
Apache:2.4.16
PHP:5.5.28
MySQL:5.6.26
ーーーーーーーーーー

  • 気になる質問をクリップする

    クリップした質問は、後からいつでもマイページで確認できます。

    またクリップした質問に回答があった際、通知やメールを受け取ることができます。

    クリップを取り消します

  • 良い質問の評価を上げる

    以下のような質問は評価を上げましょう

    • 質問内容が明確
    • 自分も答えを知りたい
    • 質問者以外のユーザにも役立つ

    評価が高い質問は、TOPページの「注目」タブのフィードに表示されやすくなります。

    質問の評価を上げたことを取り消します

  • 評価を下げられる数の上限に達しました

    評価を下げることができません

    • 1日5回まで評価を下げられます
    • 1日に1ユーザに対して2回まで評価を下げられます

    質問の評価を下げる

    teratailでは下記のような質問を「具体的に困っていることがない質問」、「サイトポリシーに違反する質問」と定義し、推奨していません。

    • プログラミングに関係のない質問
    • やってほしいことだけを記載した丸投げの質問
    • 問題・課題が含まれていない質問
    • 意図的に内容が抹消された質問
    • 広告と受け取られるような投稿

    評価が下がると、TOPページの「アクティブ」「注目」タブのフィードに表示されにくくなります。

    質問の評価を下げたことを取り消します

    この機能は開放されていません

    評価を下げる条件を満たしてません

    評価を下げる理由を選択してください

    詳細な説明はこちら

    上記に当てはまらず、質問内容が明確になっていない質問には「情報の追加・修正依頼」機能からコメントをしてください。

    質問の評価を下げる機能の利用条件

    この機能を利用するためには、以下の事項を行う必要があります。

回答 1

checkベストアンサー

0

プラグインを入れる等、手法は様々かと思いますが、 コメントアウトされているjoins部分のコードを生かした場合の回答です。

paginateのカウント処理でLEFT JOINが同じBBBを2回行いSQLエラーになります。

とありますが、bindModelのコードをそのまま残していませんか?

$this->AAA->bindModel(array('hasMany' => array('BBB'=> array('order' => 'id DESC'))),true);

$paginateにて手動で結合を指定している為、必要ありません。


  1. joins部分のコメントアウトを元に戻す
  2. bindModel部分をコメントアウト

私の環境ではこの方法で正常に動作しましたが、質問のコードだけでは分からない部分は補完しましたので、元のコードとは異なったコードです。 ひとまずこれで正常に動作するか確認していただけますでしょうか?

投稿

編集

  • 回答の評価を上げる

    以下のような回答は評価を上げましょう

    • 正しい回答
    • わかりやすい回答
    • ためになる回答

    評価が高い回答ほどページの上位に表示されます。

  • 回答の評価を下げる

    下記のような回答は推奨されていません。

    • 間違っている回答
    • 質問の回答になっていない投稿
    • スパムや攻撃的な表現を用いた投稿

    評価を下げる際はその理由を明確に伝え、適切な回答に修正してもらいましょう。

  • 2015/12/14 15:23 編集

    再度環境を組み直して検証してみました。
    paginateの呼び出し前にAAAモデルのrecursiveを-1にしてみてください。

    $this->AAA->recursive = -1;
    $data = $this->Paginator->paginate('AAA',$conditions);

    ただしこの場合$dataにBBBのデータは入ってきませんので、BBBのデータが欲しい場合はPaginatorの設定時にfieldsにて必要なカラムを指定してください。

    public $paginate = array(
    'limit' => 50,
    'maxLimit' => 1000,
    'order' => array(
    'AmznGiftCode.id' => 'asc'
    ),
    'group'=>"AmznGiftCode.id",
    'paramType' => 'querystring',
    'joins' => array(
    array(
    'type' => 'LEFT',
    'table' => 'bb_bb_bb',
    'alias' => 'BBB',
    'conditions' => 'BBB.aaa_id = AAA.id'
    )
    ),
    // ここで取得するカラムを指定
    'fields' => array('AAA.id AS a_id', 'BBB.id AS b_id', 'BBB.email AS email')
    );


    これで動くとイイナー

    キャンセル

  • 2015/12/22 15:05

    すごい遅くなってすみません。

    ありがとうざいます。
    d_s_1さんと同じようにしたらできました。

    キャンセル

  • 2015/12/22 15:21

    動いてよかったデス。

    recursiveやbindModelの設定は凄く煩わしいもので、これらを頻繁に変更するような処理はよくバグが入り込んだりします。
    出来る限りContinableビヘイビアを使っていくことをオススメします。

    キャンセル

15分調べてもわからないことは、teratailで質問しよう!

  • ただいまの回答率 90.12%
  • 質問をまとめることで、思考を整理して素早く解決
  • テンプレート機能で、簡単に質問をまとめられる