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

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

新規登録して質問してみよう
ただいま回答率
85.50%
CakePHP

CakePHPは、PHPで書かれたWebアプリケーション開発用のフレームワークです。 Ruby on Railsの考え方を多く取り入れており、Railsの高速性とPHPの機動性を兼ね備えています。 MVCやORMなどを「規約優先の考え方」で利用するため、コードを書く手間を省くことができます。 外部のライブラリに依存しないので、単体での利用が可能です。

Q&A

1回答

4122閲覧

CakePHPのSearch Plugin でhasMany検索を行う方法

d35

総合スコア8

CakePHP

CakePHPは、PHPで書かれたWebアプリケーション開発用のフレームワークです。 Ruby on Railsの考え方を多く取り入れており、Railsの高速性とPHPの機動性を兼ね備えています。 MVCやORMなどを「規約優先の考え方」で利用するため、コードを書く手間を省くことができます。 外部のライブラリに依存しないので、単体での利用が可能です。

0グッド

0クリップ

投稿2015/09/07 07:18

CakePHPのSearch Pluginを使いhasManyの検索を作成しています。フォームでチェックボッックスで複数の値を選択した場合に検索する方法を教えてください。

[開発環境]
CakePHP 2.x

(データベース)
posts(id,title)
posts_tags(id,post_id,tag_id)
tags(id,name)・・・今回は使いません(上記の2つのテーブルを利用)

Post.php(モデル)

class Post extends AppModel {
public $actsAs = array('Search.Searchable');

public $filterArgs = array(
array('name' => 'id', 'type' => 'value'),
array('name' => 'title', 'type' => 'like'),
array('name' => 'PostsTag.tag_id', 'type' => 'like'),
);

public $presetVars = array(
array('field' => 'id', 'type' => 'value'),
array('field' => 'title', 'type' => 'value'),
array('field' => 'tag_id', 'type' => 'value')
);
var $hasMany = array(
'PostsTag' => array(
'className' => 'PostsTags',
'foreignKey' => 'post_id',
'conditions' => '',
'fields' => '',
'order' => ''
));

PostsController.php(コントローラー)

class PostsController extends AppController {
public $name = 'Posts';
var $uses = array ('Post','PostsTag');
public $components = array ('Search.Prg');

function search(){
$this->presetVars = $this->Post->presetVars;
$this->Prg->commonProcess();
$req = $this->passedArgs;
$this->paginate = array(
'conditions' => $this->Post->parseCriteria($req),
'limit' => 20,
'paramType' => 'querystring',
'recursive' => 2,
);
$this->set('record', $this->paginate());

$tags = $this->Tag->find ( 'list');
$this->set(compact('tags'));
}

この状態でpr($this->paginate());を行ってみると、下記のような形でデータが表示されます。

Array
(
[0] => Array
(
[Post] => Array
(
[id] => 1
[title] => 今日は晴れです
[body] =>
)

[PostsTag] => Array ( [0] => Array ( [id] => 1 [post_id] => 1 [tag_id] => 1 ) [1] => Array ( [id] => 7 [post_id] => 1 [tag_id] => 3 ) ) ) [1] => Array ( [Post] => Array ( [id] => 2 [title] => 今日は雨です [body] => ) [PostsTag] => Array ( [0] => Array ( [id] => 2 [post_id] => 2 [tag_id] => 2 ) [1] => Array ( [id] => 8 [post_id] => 2 [tag_id] => 3 ) ) )

次にviewのフォームでtitleとpost_idという項目を作ります。
search.ctp(ビュー)

echo $this->Form->create ( 'Post', array (
'type' => 'post',
'controller' => 'posts',
'action' => 'search',
) );

echo $this->Form->input ( 'title', array ('label'=>'','class'=>'','cols'=>'','rows'=>'','value'=>''));

echo $this->Form->input( 'tag_id', array(
'type' => 'select',
'multiple'=>'checkbox',
'options' => $tags,
));
echo $this->Form->end('送信');

POSTした状態でコントローラーでpr($req);を実行してみると

Array
(
[title] => 晴れ
[tag_id] => Array
(
[0] => 3
[1] => 2
)
)
という形でデータが取得できます。

PostsTagのtag_idが2と3のどちらかが含まれるPostのidを取得するにはどのようにすれば良いのでしょうか?

hasManyはJOINではなく、複数回クエリを投げる仕組みということはわかりました。

モデルの array('name' => 'PostsTag.tag_id', 'type' => 'like'), の部分でクエリを作って設定するか、コントローラの$reqに直接記載するなどの方法が考えられますが、どのようにプログラムを書いたらいかがわかりません。

ご回答よろしくお願いします。

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

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

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

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

guest

回答1

0

他の質問でSearchプラグインを使う機会がありましたので、こちらの質問も調べてみました。
動作したモデルをそのまま載せます。

PHP

1<?php 2App::uses('AppModel', 'Model'); 3 4class Post extends AppModel { 5 public $actsAs = array('Search.Searchable'); 6 7 public $hasMany = array( 'PostsTag' => array( 'className' => 'PostsTags' 8 , 'foreignKey' => 'post_id' 9 , 'conditions' => '' 10 , 'fields' => '' 11 , 'order' => '')); 12 13 public $filterArgs = array( array( 'name' => 'id' 14 , 'type' => 'value') 15 , array( 'name' => 'title' 16 , 'type' => 'like') 17 , array( 'name' => 'tag_id' 18 , 'type' => 'query' 19 , 'field' => 'PostsTag.tag_id' 20 , 'method' => 'searchTagId')); 21 22 public $presetVars = array( array( 'field' => 'id' 23 , 'type' => 'value') 24 , array( 'field' => 'title' 25 , 'type' => 'value') 26 , array( 'field' => 'tag_id' 27 , 'type' => 'value')); 28 29 public function searchTagId($searchs = array()){ 30 /* 31 $searchsに条件(tag_id)が入っているので、 32 それを元にPostsTagから取得対象のpost_idを取得し、 33 Postの取得条件としてpost_idを用いた条件を返す。 34 */ 35 $conditions = array(); 36 if(isset($searchs['tag_id'])){ 37 $posts_tags_conditions = array(); 38 foreach($searchs['tag_id'] as $search){ 39 $posts_tags_conditions['or']['PostsTag.tag_id'][] = $search; 40 } 41 if(!empty($posts_tags_conditions)){ 42 $PostsTagItems = $this->PostsTag->find('all', array('conditions' => $posts_tags_conditions)); 43 foreach($PostsTagItems as $PostsTagItem){ 44 $conditions['or'][] = array('Post.id' => $PostsTagItem['PostsTag']['post_id']); 45 } 46 } 47 } 48 return $conditions; 49 } 50}

$filterArgsでメソッドを指定して、そのメソッドでpost_idを用いたPostの取得条件を作成すればOKですね。

投稿2016/02/12 05:53

編集2016/02/12 05:55
退会済みユーザー

退会済みユーザー

総合スコア0

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

まだベストアンサーが選ばれていません

会員登録して回答してみよう

アカウントをお持ちの方は

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

ただいまの回答率
85.50%

質問をまとめることで
思考を整理して素早く解決

テンプレート機能で
簡単に質問をまとめる

質問する

関連した質問