ユーザー情報を管理する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を使用)
//Model/User.php
<?php
App::uses('AuthComponent', 'Controller/Component');
class User extends AppModel {
public $hasMany = array('Tweet');
?>
//Model/Tweet.php
<?php
class Tweet extends AppModel {
public $belongsTo = 'User';
public $actsAs = array('Search.Searchable');
public $filterArgs = array(
'tweet' => array('type' => 'like')
);
}
?>
//Controller/TweetsController
<?php
class TweetsController extends AppController {
public $components = array('Search.Prg');
public $presetVars = true;
public $paginate = array();
public function search() {
$this->paginate = array(
'limit' => 100,
);
$this->Prg->commonProcess();
$this->paginate['conditions'] = $this->Tweet->parseCriteria($this->passedArgs);
$tweetLists = $this->paginate();
$this->set(compact('tweetLists'));
}
}
?>
//View/Tweets/search.ctp
<div>
<?php echo $this->Form->create('Tweet',array(
'novalidate' => true,
'url' => array_merge(array('action' => 'search'),
$this->params['pass'])
));
?>
<?php echo $this->Form->input('tweet', array(
'type' => 'text',
'placeholder' => '検索ワードを入力してください',
'label' => false
)); ?>
<?php echo $this->Form->submit('検索'); ?>
<?php echo $this->Form->end(); ?>
</div>
<div>
<h2>検索結果</h2>
<table>
<tr>
<th><?php echo $this->Paginator->sort('User.username', 'ユーザー名'); ?></th>
<th><?php echo $this->Paginator->sort('tweet', 'つぶやき'); ?></th>
</tr>
<?php foreach($tweetLists as $tweetList): ?>
<tr>
<td><?php echo $this->Html->link($tweetList['User']['username'],'/users/view/'.$tweetList['User']['id']) ?></td>
<td><?php echo h($tweetList['Tweet']['tweet']); ?></td>
</tr>
<?php endforeach; ?>
</table>
</div>
<div>
<?php echo $this->Paginator->prev(); ?>
<?php echo $this->Paginator->numbers(); ?>
<?php echo $this->Paginator->next(); ?>
</div>
-
気になる質問をクリップする
クリップした質問は、後からいつでもマイページで確認できます。
またクリップした質問に回答があった際、通知やメールを受け取ることができます。
クリップを取り消します
-
良い質問の評価を上げる
以下のような質問は評価を上げましょう
- 質問内容が明確
- 自分も答えを知りたい
- 質問者以外のユーザにも役立つ
評価が高い質問は、TOPページの「注目」タブのフィードに表示されやすくなります。
質問の評価を上げたことを取り消します
-
評価を下げられる数の上限に達しました
評価を下げることができません
- 1日5回まで評価を下げられます
- 1日に1ユーザに対して2回まで評価を下げられます
質問の評価を下げる
teratailでは下記のような質問を「具体的に困っていることがない質問」、「サイトポリシーに違反する質問」と定義し、推奨していません。
- プログラミングに関係のない質問
- やってほしいことだけを記載した丸投げの質問
- 問題・課題が含まれていない質問
- 意図的に内容が抹消された質問
- 過去に投稿した質問と同じ内容の質問
- 広告と受け取られるような投稿
評価が下がると、TOPページの「アクティブ」「注目」タブのフィードに表示されにくくなります。
質問の評価を下げたことを取り消します
この機能は開放されていません
評価を下げる条件を満たしてません
質問の評価を下げる機能の利用条件
この機能を利用するためには、以下の事項を行う必要があります。
- 質問回答など一定の行動
-
メールアドレスの認証
メールアドレスの認証
-
質問評価に関するヘルプページの閲覧
質問評価に関するヘルプページの閲覧
checkベストアンサー
+1
おそらく取得したい情報を1回のSQLで取得しようとすると、以下のようなSQLになると思います
SELECT
Tweet.user_id,
User.username,
group_concat(Tweet.tweet SEPARATOR ' | ')
FROM
tweets AS Tweet
LEFT JOIN users AS User ON (tweet.user_id = User.user_id)
where
Tweet.user_id IN (select DISTINCT user_id from tweets where tweets.tweet like '%お腹%')
group by Tweet.user_id
このまま1回のSQLで実現するのは難しいと判断したので、サブクエリでのuser_idの取得部分とそれをパラメータとしたtweetの取得部分の二つに分けて実装してみました
//Controller/TweetsController
<?php
class TweetsController extends AppController {
public $components = array('Search.Prg');
public $presetVars = true;
public $paginate = array();
public $userid = array();
public $uses = array('Tweet','user','wkTweet');
public function search() {
$this->paginate = array(
'limit' => 100,
);
$this->Prg->commonProcess();
// 最初につぶやきを検索して対象のuser_idを取得
$this->userid['conditions'] = $this->Tweet->parseCriteria($this->passedArgs);
$this->userid['fields'] = array('DISTINCT Tweet.user_id');
$array_user_id = $this->Tweet->find('all', $this->userid);
$user_ids = array();
foreach ($array_user_id as $wkTweet) {
$user_ids[] = $wkTweet['Tweet']['user_id'];
}
$user_id['user_id'] = implode(',', $user_ids);
// そのユーザIDで対象の全つぶやきを取得して編集
$this->paginate['conditions'] = $this->Tweet->parseCriteria($user_id);
$this->paginate['fields'] = array('Tweet.user_id','User.username', 'group_concat(tweet SEPARATOR "|") as tweets');
$this->paginate['group'] = array('Tweet.user_id');
$tweetLists = $this->paginate();
$this->set(compact('tweetLists'));
}
}
?>
//Model/Tweet.php
class Tweet extends AppModel {
public $belongsTo = 'User';
public $actsAs = array('Search.Searchable');
public $filterArgs = array(
'tweet' => array('type' => 'like'),
'user_id' => array('type' => 'subquery','method' => 'searchIn', 'field' => 'Tweet.user_id')
);
function searchIn($data = array()) {
$query = $data['user_id'];
return $query;
}
}
//View/Tweets/search.ctp
<?php echo $this->Form->create('Tweet',array(
'novalidate' => true,
'url' => array_merge(array('action' => 'search'),
$this->params['pass'])
));
?>
<?php echo $this->Form->input('tweet', array(
'type' => 'text',
'placeholder' => '検索ワードを入力してください',
'label' => false
)); ?>
<?php echo $this->Form->submit('検索'); ?>
<?php echo $this->Form->end(); ?>
</div>
<div>
<h2>検索結果</h2>
<table>
<tr>
<th><?php echo $this->Paginator->sort('User.username', 'ユーザー名'); ?></th>
<th><?php echo $this->Paginator->sort('tweet', 'つぶやき'); ?></th>
</tr>
<?php foreach($tweetLists as $tweetList): ?>
<tr>
<td><?php echo $this->Html->link($tweetList['User']['username'],'/users/view/'.$tweetList['Tweet']['user_id']) ?></td>
<td><?php echo h($tweetList[0]['tweets']); ?></td>
</tr>
<?php endforeach; ?>
</table>
</div>
<div>
<?php echo $this->Paginator->prev(); ?>
<?php echo $this->Paginator->numbers(); ?>
<?php echo $this->Paginator->next(); ?>
</div>
Model/User.phpについては、変更はありません
また、Group Byを使用しているので、ページネート処理が上手く行くかまでは検証していません
おそらくですが、このままではレコード総数の取得が上手く行かないため、ページ処理ではエラーが出ると思います・・・
投稿
-
回答の評価を上げる
以下のような回答は評価を上げましょう
- 正しい回答
- わかりやすい回答
- ためになる回答
評価が高い回答ほどページの上位に表示されます。
-
回答の評価を下げる
下記のような回答は推奨されていません。
- 間違っている回答
- 質問の回答になっていない投稿
- スパムや攻撃的な表現を用いた投稿
評価を下げる際はその理由を明確に伝え、適切な回答に修正してもらいましょう。
15分調べてもわからないことは、teratailで質問しよう!
- ただいまの回答率 88.20%
- 質問をまとめることで、思考を整理して素早く解決
- テンプレート機能で、簡単に質問をまとめられる
2015/12/28 18:49
おかげさまで希望の動作を実装することが出来ました。
ページネートも、正しく動作しているように見えます。
回答いただいたソースも理解できるように勉強していこうと思います。