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

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

ただいまの
回答率

90.51%

  • CakePHP

    2518questions

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

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

解決済

回答 2

投稿 編集

  • 評価
  • クリップ 0
  • VIEW 1,963

atsupoooon

score 32

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'
)

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

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

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

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

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

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

    クリップを取り消します

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

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

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

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

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

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

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

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

    質問の評価を下げる

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

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

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

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

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

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

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

    詳細な説明はこちら

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

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

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

回答 2

checkベストアンサー

+3

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

// Model/Comment.php counterCacheの有効化
class Comment extends AppModel{
    public $belongsTo = array('Post' => array('counterCache' => true));
}
/* postsテーブルに「モデル名の単数形_count」という名前のカラムを作成*/
ALTER TABLE `posts` ADD `comment_count` INT NOT NULL;


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


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

// Controller
$this->set('items', $this->Post->find('all'));
// View
foreach($items as $item){
    echo '投稿ID:' . $item['Post']['id'] . ' | コメント件数:' . $item['Post']['comment_count'];
}

投稿

編集

  • 回答の評価を上げる

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

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

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

  • 回答の評価を下げる

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

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

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

  • 2016/02/01 13:56

    回答ありがとうございます。

    counterCacheという記述があるのを初めて知りました。
    ありがとうございます。

    実装できました!
    マニュアルをもう一度読み返してみます!

    少し違う話になるのですが、counterCacheを使用すると
    facebookなどであるいいねの機能なども実装しやすいですよね?

    キャンセル

  • 2016/02/01 14:08 編集

    出来たようで良かったです。

    他のテーブルと連携しなくてもhasMany先のカウントが出来るのは大きなメリットですが、もちろんデメリットもあります。

    Model::save(),Model::delete()を実行し、それに関連したデータのみが更新対象です。
    Model::updateAllを使用するような一括の処理等では更新されません。
    なのでModel::updateCounterCache()を実行して別途更新が必要です。

    いいねボタンの実装にも有用な機能だと思いますが、counterCacheの更新されるタイミングについては気を付けて下さい。

    私はPHPMyAdminで直接hasMany先のデータを増やした後、counterCacheの更新を忘れてしまうことが多々あります・・・

    キャンセル

  • 2016/02/01 14:59

    updateAllでは、更新されないのですね。

    タイミング。。わかるようなわからないような感じです。。
    とりあえず自分で考えて実装してみます!
    ありがとうございます。

    なるごどです!
    ご指導ありがとうございます。

    キャンセル

+1

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

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

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

投稿

  • 回答の評価を上げる

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

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

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

  • 回答の評価を下げる

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

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

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

  • 2016/02/01 13:41 編集

    ご回答ありがとうございます。

    今view側で試してみましたが、
    表示できませんでした。

    foreach ($posts as $post) {
    echo $post['title'].$results_tmp[$post['id']];
    }

    ではダメでした。

    idが未定義の変数としてエラーがでます。

    キャンセル

  • 2016/02/01 15:01

    解決したのですが、foreachからの取得方法も
    教えていただければ幸いです。

    foreachがどうも苦手なので。
    理解できていない部分がありますので。。。

    キャンセル

  • 2016/02/01 22:51

    解決してよかったです!

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

    キャンセル

  • 2016/02/01 23: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で右の数字がコメント数であるのは、
    間違いないのですが、
    どのようにこのコメント数を表示させればいいかがわからない状態です。
    たぶん、コントローラー側での処理を完全に理解できていないからだと思いますが。。。

    すいません。

    以前も同じようなパターンでハマってしましまったのでなんとかモヤモヤを。。。笑

    キャンセル

  • 2016/02/02 00:59

    そうですね。ハマったところは解決しておきたいですよね。笑
    私でよければ一緒に見ていきましょう。

    foreach ($posts as $post) {
    echo $post['title'].$results_tmp[$post['id']];
    }

    このコードで「idが未定義の変数」という内容のエラーが出るということなので、そのエラーの原因をつきとめましょう。
    次の二つの出力を教えてもらえますか。公開できる範囲で構いませんので。
    1. debug($results_tmp[2]);
    2. debug($posts);

    キャンセル

  • 2016/02/02 17: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'
    ),

    で正しくデータが返ってきている。
    という状態です。

    キャンセル

  • 2016/02/02 20: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が取得できることが分かります。
    ---------------------------

    ひたすら変数の中身確認していくのが鉄則ですね。

    キャンセル

  • 2016/02/02 22:40

    なるほど!!!!!!
    ものすごく分かりやすいご説明ありがとうございます!!

    すごくしっくりきました!
    必ず変数の中を確認する作業が必要ですね!

    やっと、ちゃんと理解できました!!!

    1から教えていただき誠にありがとうございます。

    また、ご指導のほど宜しくお願い致します。

    キャンセル

同じタグがついた質問を見る

  • CakePHP

    2518questions

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