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

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

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

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

Q&A

解決済

1回答

2659閲覧

[CakePHP 2.X]Search Pluginを用いたつぶやき検索で、ヒットしたつぶやきを持つuse_idの他のつぶやきを表示

hiro_87g

総合スコア28

CakePHP

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

0グッド

0クリップ

投稿2015/12/20 06:53

編集2015/12/21 09:36

ユーザー情報を管理するUserテーブルと、つぶやき情報を管理するTweetテーブルがあります。

UserはhasmanyでTweetを持っています。
TweetはbelongsToでUserに属しています。

Search Pluginで検索した時に、ヒットした「つぶやき」を持つuser_idの他の「つぶやき」も参考として表示させたいと思っているのですが、方法が分かりません。

・Tweetの方からSearch pluginを使うことで、検索に該当したつぶやきのみは表示できていますが、同userの他のつぶやきを表示する方法が分かりません。(参考までに下記にソースを記載しています)

・Userの方からSearch pluginが使えればいける気もしましたが、hasmanyで持っているテーブル内を検索対象にする方法が分かりませんでした。

Tweet内でSearch pluginを使用 or User内でSearch pluginを使用、
実現したいことができれば、このどちらでも(もしくは他の方法でも)構わないのですが
良い方法がありましたらお教えいただけますと助かります。

何卒よろしくお願いします。

■cakeのバージョン:2.7

■データベース
Userテーブル(ユーザー)

ID|username 1 太郎 2 花子 ・ ・ Tweetテーブル(つぶやき)

ID | tweet | user_id
1 暑いなー 1
2 お腹いっぱい 1
3 楽しい! 1
4 お腹空いた 2
5 いい天気 2
6 風邪ひいた 2
7 嬉しい 2

■現状
現状


■完成イメージ(画像編集ソフトで作成しました)
完成イメージ

■現状のソース(Tweetの方からSearch pluginを使用)

lang

1//Model/User.php 2<?php 3App::uses('AuthComponent', 'Controller/Component'); 4class User extends AppModel { 5 public $hasMany = array('Tweet'); 6?>

lang

1//Model/Tweet.php 2<?php 3class Tweet extends AppModel { 4 public $belongsTo = 'User'; 5 public $actsAs = array('Search.Searchable'); 6 public $filterArgs = array( 7 'tweet' => array('type' => 'like') 8 ); 9} 10?>

lang

1//Controller/TweetsController 2<?php 3 4class TweetsController extends AppController { 5 6 public $components = array('Search.Prg'); 7 public $presetVars = true; 8 public $paginate = array(); 9 10 public function search() { 11 $this->paginate = array( 12 'limit' => 100, 13 ); 14 $this->Prg->commonProcess(); 15 $this->paginate['conditions'] = $this->Tweet->parseCriteria($this->passedArgs); 16 $tweetLists = $this->paginate(); 17 $this->set(compact('tweetLists')); 18 } 19} 20?>

lang

1//View/Tweets/search.ctp 2<div> 3 <?php echo $this->Form->create('Tweet',array( 4 'novalidate' => true, 5 'url' => array_merge(array('action' => 'search'), 6 $this->params['pass']) 7 )); 8 ?> 9 <?php echo $this->Form->input('tweet', array( 10 'type' => 'text', 11 'placeholder' => '検索ワードを入力してください', 12 'label' => false 13 )); ?> 14 <?php echo $this->Form->submit('検索'); ?> 15 <?php echo $this->Form->end(); ?> 16 </div> 17 18 <div> 19 <h2>検索結果</h2> 20 <table> 21 <tr> 22 <th><?php echo $this->Paginator->sort('User.username', 'ユーザー名'); ?></th> 23 <th><?php echo $this->Paginator->sort('tweet', 'つぶやき'); ?></th> 24 </tr> 25 26 <?php foreach($tweetLists as $tweetList): ?> 27 28 <tr> 29 <td><?php echo $this->Html->link($tweetList['User']['username'],'/users/view/'.$tweetList['User']['id']) ?></td> 30 <td><?php echo h($tweetList['Tweet']['tweet']); ?></td> 31 </tr> 32 33 <?php endforeach; ?> 34 35 </table> 36 </div> 37 38 <div> 39 <?php echo $this->Paginator->prev(); ?>&nbsp; 40 <?php echo $this->Paginator->numbers(); ?>&nbsp; 41 <?php echo $this->Paginator->next(); ?> 42 </div>

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

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

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

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

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

guest

回答1

0

ベストアンサー

おそらく取得したい情報を1回のSQLで取得しようとすると、以下のようなSQLになると思います

SQL

1SELECT 2 Tweet.user_id, 3 User.username, 4 group_concat(Tweet.tweet SEPARATOR ' | ') 5FROM 6 tweets AS Tweet 7 LEFT JOIN users AS User ON (tweet.user_id = User.user_id) 8where 9 Tweet.user_id IN (select DISTINCT user_id from tweets where tweets.tweet like '%お腹%') 10group by Tweet.user_id

このまま1回のSQLで実現するのは難しいと判断したので、サブクエリでのuser_idの取得部分とそれをパラメータとしたtweetの取得部分の二つに分けて実装してみました

PHP

1//Controller/TweetsController 2<?php 3class TweetsController extends AppController { 4 5 public $components = array('Search.Prg'); 6 public $presetVars = true; 7 public $paginate = array(); 8 public $userid = array(); 9 public $uses = array('Tweet','user','wkTweet'); 10 11 public function search() { 12 $this->paginate = array( 13 'limit' => 100, 14 ); 15 16 $this->Prg->commonProcess(); 17 // 最初につぶやきを検索して対象のuser_idを取得 18 $this->userid['conditions'] = $this->Tweet->parseCriteria($this->passedArgs); 19 $this->userid['fields'] = array('DISTINCT Tweet.user_id'); 20 21 $array_user_id = $this->Tweet->find('all', $this->userid); 22 23 $user_ids = array(); 24 foreach ($array_user_id as $wkTweet) { 25 $user_ids[] = $wkTweet['Tweet']['user_id']; 26 } 27 28 $user_id['user_id'] = implode(',', $user_ids); 29 30 // そのユーザIDで対象の全つぶやきを取得して編集 31 $this->paginate['conditions'] = $this->Tweet->parseCriteria($user_id); 32 $this->paginate['fields'] = array('Tweet.user_id','User.username', 'group_concat(tweet SEPARATOR "|") as tweets'); 33 $this->paginate['group'] = array('Tweet.user_id'); 34 $tweetLists = $this->paginate(); 35 $this->set(compact('tweetLists')); 36 } 37} 38?>

PHP

1//Model/Tweet.php 2class Tweet extends AppModel { 3 public $belongsTo = 'User'; 4 public $actsAs = array('Search.Searchable'); 5 public $filterArgs = array( 6 'tweet' => array('type' => 'like'), 7 'user_id' => array('type' => 'subquery','method' => 'searchIn', 'field' => 'Tweet.user_id') 8 ); 9 10 function searchIn($data = array()) { 11 $query = $data['user_id']; 12 return $query; 13 } 14}

PHP

1//View/Tweets/search.ctp 2 <?php echo $this->Form->create('Tweet',array( 3 'novalidate' => true, 4 'url' => array_merge(array('action' => 'search'), 5 $this->params['pass']) 6 )); 7 ?> 8 <?php echo $this->Form->input('tweet', array( 9 'type' => 'text', 10 'placeholder' => '検索ワードを入力してください', 11 'label' => false 12 )); ?> 13 <?php echo $this->Form->submit('検索'); ?> 14 <?php echo $this->Form->end(); ?> 15 </div> 16 17 <div> 18 <h2>検索結果</h2> 19 <table> 20 <tr> 21 <th><?php echo $this->Paginator->sort('User.username', 'ユーザー名'); ?></th> 22 <th><?php echo $this->Paginator->sort('tweet', 'つぶやき'); ?></th> 23 </tr> 24 25 <?php foreach($tweetLists as $tweetList): ?> 26 27 <tr> 28 <td><?php echo $this->Html->link($tweetList['User']['username'],'/users/view/'.$tweetList['Tweet']['user_id']) ?></td> 29 <td><?php echo h($tweetList[0]['tweets']); ?></td> 30 </tr> 31 32 <?php endforeach; ?> 33 34 </table> 35 </div> 36 37 <div> 38 <?php echo $this->Paginator->prev(); ?>&nbsp; 39 <?php echo $this->Paginator->numbers(); ?>&nbsp; 40 <?php echo $this->Paginator->next(); ?> 41 </div>

Model/User.phpについては、変更はありません
また、Group Byを使用しているので、ページネート処理が上手く行くかまでは検証していません
おそらくですが、このままではレコード総数の取得が上手く行かないため、ページ処理ではエラーが出ると思います・・・

投稿2015/12/25 06:22

KatsumiTanaka

総合スコア924

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

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

hiro_87g

2015/12/28 09:49

大変丁寧なご回答、ありがとうございました。 おかげさまで希望の動作を実装することが出来ました。 ページネートも、正しく動作しているように見えます。 回答いただいたソースも理解できるように勉強していこうと思います。
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

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

ただいまの回答率
85.51%

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

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

質問する

関連した質問