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

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

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

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

Q&A

解決済

2回答

4531閲覧

cakephpでコメントの件数を表示したいのですができません。

atsupoooon

総合スコア47

CakePHP

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

0グッド

0クリップ

投稿2016/01/30 04:10

編集2016/01/30 05:29

CakePHP 2.6
php 5.6

投稿した個別の記事ないには、コメント件数を表示できましたが、
一覧ページにも表示したいのですが、できません。

find('count')で表示させようとしております。

実装したい内容としては、
・投稿した一覧画面に投稿に対してのコメント数を表示
※投稿した個別のページでは実装できました。

現在イメージしている処理の内容ですが、下記になるかと思っています。
1、controller : commentのpost_id=postsのidの値を取得
2、view : ループを回して表示する。

というイメージなのですが、このイメージで正しいのでしょうか?

この上記のイメージが間違っていました。

自分なりに考え直した結果。これが正しい処理の方法かと思っています。
1、controller
・virtualFieldsを追加。
・find('all')で指定のfieldsの取得して、countで合計を出す。
・それをpostのidでグループ化
・combineで配列を組み直す
・最後にviewに渡す。

しかし、viewに渡してからの表示方法がわかりません。。。

コントローラーからのviewに返ってきた値は、
下記になります。
array(
'' => '0',
(int) 2 => '16',
(int) 4 => '5',
(int) 7 => '15',
(int) 8 => '7',
(int) 9 => '1',
(int) 13 => '3',
(int) 17 => '3',
(int) 18 => '1',
(int) 19 => '1',
(int) 28 => '3',
(int) 33 => '3'
)

コントローラーがこちらです。

php

1//コメント件数表示 2 $this->Post->virtualFields['num'] = 0; 3 $data = $this->Post->Comment->find('all', array( 4 'fields'=> array('Post.id', 'Comment.cosme_id', 'count(Post.id) as Post__num'), 5 'group' => array('Post.id') 6 )); 7 $results_tmp = Hash::combine($data, '{n}.Post.id', '{n}.Post.num'); 8 $this->set(compact('results_tmp'));

最後のviewので表示ができません。
宜しくお願い致します。

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

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

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

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

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

guest

回答2

0

ベストアンサー

counterCacheを使用するともっとシンプルに実現出来るかと思います。
実装も非常に簡単です。
参考:アソシエーション: モデル同士を繋ぐ

PHP

1// Model/Comment.php counterCacheの有効化 2class Comment extends AppModel{ 3 public $belongsTo = array('Post' => array('counterCache' => true)); 4}

SQL

1/* postsテーブルに「モデル名の単数形_count」という名前のカラムを作成*/ 2ALTER TABLE `posts` ADD `comment_count` INT NOT NULL;

以上の設定でcounterCacheが有効になります。
Model::save()などのメソッドを実行したタイミングで、
投稿に対するコメントの件数がposts.comment_countに都度設定されます。


counterCacheを用いた場合の質問の回答は↓。

PHP

1// Controller 2$this->set('items', $this->Post->find('all'));

PHP

1// View 2foreach($items as $item){ 3 echo '投稿ID:' . $item['Post']['id'] . ' | コメント件数:' . $item['Post']['comment_count']; 4}

投稿2016/02/01 01:43

編集2016/02/01 01:47
退会済みユーザー

退会済みユーザー

総合スコア0

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

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

atsupoooon

2016/02/01 04:56

回答ありがとうございます。 counterCacheという記述があるのを初めて知りました。 ありがとうございます。 実装できました! マニュアルをもう一度読み返してみます! 少し違う話になるのですが、counterCacheを使用すると facebookなどであるいいねの機能なども実装しやすいですよね?
退会済みユーザー

退会済みユーザー

2016/02/01 05:15 編集

出来たようで良かったです。 他のテーブルと連携しなくてもhasMany先のカウントが出来るのは大きなメリットですが、もちろんデメリットもあります。 Model::save(),Model::delete()を実行し、それに関連したデータのみが更新対象です。 Model::updateAllを使用するような一括の処理等では更新されません。 なのでModel::updateCounterCache()を実行して別途更新が必要です。 いいねボタンの実装にも有用な機能だと思いますが、counterCacheの更新されるタイミングについては気を付けて下さい。 私はPHPMyAdminで直接hasMany先のデータを増やした後、counterCacheの更新を忘れてしまうことが多々あります・・・
atsupoooon

2016/02/01 05:59

updateAllでは、更新されないのですね。 タイミング。。わかるようなわからないような感じです。。 とりあえず自分で考えて実装してみます! ありがとうございます。 なるごどです! ご指導ありがとうございます。
guest

0

質問内容を拝見すると、あとはビューに配列の内容を出力するだけですよね。
投稿一覧も表示できているみたいですし。

投稿一覧を表示する際に多分ループを回して出力していると思うのですが、その時に配列$results_tmp(表示したい配列)に対して、投稿のidをキーとして値を出力できないでしょうか。

foreach (投稿たち as 投稿) { echo 投稿['タイトル'].$results_tmp[投稿['id']]; }

投稿2016/01/31 07:58

coba-coba

総合スコア1409

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

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

atsupoooon

2016/02/01 04:57 編集

ご回答ありがとうございます。 今view側で試してみましたが、 表示できませんでした。 foreach ($posts as $post) { echo $post['title'].$results_tmp[$post['id']]; } ではダメでした。 idが未定義の変数としてエラーがでます。
atsupoooon

2016/02/01 06:01

解決したのですが、foreachからの取得方法も 教えていただければ幸いです。 foreachがどうも苦手なので。 理解できていない部分がありますので。。。
coba-coba

2016/02/01 13:51

解決してよかったです! foreachの件は、ビューでdebug($posts);してみて、投稿idを$post['id']で取得できるかを確認してみましょう。 $postは考えている通りのデータ構造になっていますか? $postsと$results_tmpが何のデータを持っていて、どのようにビューに送られているかを整理すると、解決できるかと思います。
atsupoooon

2016/02/01 14:57

回答ありがとうございます。 idの取得はできました。 $results_tmpがどんなデータを持っているかも 理解できるのですが、 下記のようにviewに返ってきているので、 array( '' => '0', (int) 2 => '16', (int) 4 => '5', (int) 7 => '15', (int) 8 => '7', (int) 9 => '1', (int) 13 => '3', (int) 17 => '3', (int) 18 => '1', (int) 19 => '1', (int) 28 => '3', (int) 33 => '3' ) int型の数字がidで右の数字がコメント数であるのは、 間違いないのですが、 どのようにこのコメント数を表示させればいいかがわからない状態です。 たぶん、コントローラー側での処理を完全に理解できていないからだと思いますが。。。 すいません。 以前も同じようなパターンでハマってしましまったのでなんとかモヤモヤを。。。笑
coba-coba

2016/02/01 15:59

そうですね。ハマったところは解決しておきたいですよね。笑 私でよければ一緒に見ていきましょう。 foreach ($posts as $post) { echo $post['title'].$results_tmp[$post['id']]; } このコードで「idが未定義の変数」という内容のエラーが出るということなので、そのエラーの原因をつきとめましょう。 次の二つの出力を教えてもらえますか。公開できる範囲で構いませんので。 1. debug($results_tmp[2]); 2. debug($posts);
atsupoooon

2016/02/02 08:30

回答ありがとうございます。 なんども申し訳ありません。 自分でなんとか解決できました。 下記でできました!! <?php $data = $results_tmp[$post['Post']['id']]; if(empty($data)) { echo "データなし"; } echo $results_tmp[$post['Post']['id']]; ?> しかしなぜ、$results_tmp[$post['Post']['id']];で取得できるか かがイマイチ理解できていません。 正直当てずっぽです。笑 idが必要なのはわかるのですが、 少しコントローラー側でデータをviewに渡す記述が変わると ハマります。。笑 1. debug($results_tmp[2]); ===17 投稿id 2に17件のコメントが紐づいている。 2. debug($posts); array( (int) 0 => array( 'Post' => array( 'id' => '2', 'title' => 'タイトル', 'body01' => '本文1', 'img01_file_name' => 'test.jpg', 'body02' => '本文2', 'body03' => '本文3', 'category_id' => '2', 'created' => '2016-01-22 14:59:12', 'modified' => '2016-01-22 14:59:12', 'comment_count' => '17' ), で正しくデータが返ってきている。 という状態です。
coba-coba

2016/02/02 11:56

好きでやっているので、何度でも構いませんよ。笑 解決できてよかったです。 CakePHP2は、アソシエーションで複数のモデルからまとめてデータを取得できるので、取得するデータを区別するためにモデル名を使います。 find('all')をした場合は、取得する結果は次のような構成になります。(マニュアルから引用 http://book.cakephp.org/2.0/ja/models/retrieving-your-data.html ) Array ( [0] => Array ( [ModelName] => Array ( [id] => 83 [field1] => value1 [field2] => value2 [field3] => value3 ) [AssociatedModelName] => Array ( [id] => 1 [field1] => value1 [field2] => value2 [field3] => value3 ) ) ) 最初の[0]は1つ目のデータということです。 2つあれば、2つ目は[1]。 3つあれば3つ目は[2]、と増えていきます。 foreachでは、その値を1つずつ取り出して処理していきます。 次に、[ModelName]と[AssociatedModelName]は、取得したデータをモデルで区別しています。 今回はPostモデルを使用しているので、Postをキーとして値を取得しました。 foreach($posts as $post)とした場合には、$postsから1つずつ取り出して、$post['Post']['id']として投稿idを取得していますが、 foreachを使わない場合は、取得した投稿の数だけ、$posts[0]['Post']['id']、$posts[1]['Post']['id']、$posts[2]['Post']['id']…としても投稿idを取得することができます。 --------------------------- debug($posts);で中身を確認すると、最初に(int) 0とあるので、$posts[0]でデータを取得できることが分かります。 更に、 array( 'Post' => とあるので、$posts[0]['Post']で更に値を取得できます。 更に更に、 array( 'id' => '2', とあるので、$posts[0]['Post']['id']で投稿idが取得できることが分かります。 --------------------------- ひたすら変数の中身確認していくのが鉄則ですね。
atsupoooon

2016/02/02 13:40

なるほど!!!!!! ものすごく分かりやすいご説明ありがとうございます!! すごくしっくりきました! 必ず変数の中を確認する作業が必要ですね! やっと、ちゃんと理解できました!!! 1から教えていただき誠にありがとうございます。 また、ご指導のほど宜しくお願い致します。
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

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

ただいまの回答率
85.51%

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

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

質問する

関連した質問