コメント一覧でコメントに対するコメントが正しく表示される記述方法をお教え願います。

投稿者: Anonymous

お世話になります。どうかご教授頂けませんでしょうか。
サイト作成で、商品に関するコメント一覧ページを作成しております。その一覧で、ある商品のコメントに対する返信、つまりコメントに対するコメント(子コメント)を以下の様にコメントA(親コメント)の下に延々と表示できるようにしたいのですが、現在の状況はその下の様な状況になっており、同じコメントAが重複されます。

・期待する表示

コメントA
   コメントAに対するコメントa1
       コメントAに対するコメントa2
       コメントAに対するコメントa3
       コメントAに対するコメントa4

コメントB
       ………………………………………
       ……………………………………….
コメントC
       ………………………………………
       ……………………………………….

・ 現在の表示

コメントA
      コメントAに対するコメントa1
コメントA
      コメントAに対するコメントa2
コメントA
      コメントAに対するコメントa3
コメントA
      コメントAに対するコメントa4

コメントB
       ………………………………………
       ……………………………………….
コメントC
       ………………………………………
       ……………………………………….

以下は以上の設定の必要最小限を記載したDB、PHP、Smartyでの記述でございます。問題点は何かをご指摘いただけませんでしょうか。あるいはこのようなケースの場合、どのような設定にするのが最適かご教授頂けませんでしょうか。

DB

親コメント用テーブル(dtb_review)     
review_id                              
product_id                              
reviewer_name                         
Comment                                                          
Create_date

子コメント用テーブル(dtb_review2)
review_id
original_review_id
reviewer_name
comment
Create_date

*dtb_reviewのreview_idとdtb_review2のoriginal_review_idは同じid(番号)です。

PHP

$col = "t1.review_id, t1.comment, t1.del_flg, t1.create_date, t1.product_id, t1.reviewer_name, t2.product_id, t5.original_review_id, t5.comment2, t5.reviewer_name, t5.create_date";

$from = "dtb_review as t1 
left join dtb_products as t2 using (product_id)
left join dtb_review2 as t5 ON t1.review_id = t5.original_review_id";

$where = " t1.del_flg = 0 ORDER BY t1.create_date DESC";

$this->arrReview = $objQuery->select($col, $from, $where, $arrval); 

Smarty

{section name=cnt loop=$arrReview}

{$arrReview[cnt].comment|h|nl2br}(親コメント)

{if $arrReview[cnt].review_id|h == $arrReview[cnt].original_review_id|h }

{section2 name=cnt loop=$arrReview}

{$arrReview[cnt].comment2|h|nl2br}(子コメント)

{/section2}

{else}
{/if}

{/section}

*あるコメントに対してコメントされると、つまり親コメントに対して子コメントが作成されるとdtb_reviewのreview_idがdtb_review2のoriginal_review_idに渡ります。

解決

親コメント、子コメントとそれぞれテーブルを分けていることで分かりにくくなっているのではないでしょうか?
このケースの場合、dtb_reviewと、productテーブルのみで実装可能です。

//reviewテーブル
review_id 
parent_review_id //親コメントの場合はNULL, 子コメントの場合は親のreview_id                             
product_id                              
reviewer_name                         
comment                                                          
create_date

parent_review_idには、親コメントの場合はNULL,子コメントの場合は親コメントのreview_idが挿入されるようにします。(サンプル内dtb_review2のoriginal_review_idのような役割です)

sql

SELECT
  t1.review_id,
  t1.parent_review_id,
  t1.comment,
  t1.del_flag,
  t1.create_date,
  t1.product_id,
  t1.reviewer_name,
  t2.product_id,
  CASE WHEN t1.parent_review_id IS NULL THEN t1.review_id ELSE t1.parent_review_id END as root_review_id
FROM dtb_review AS t1
  LEFT JOIN dtb_products AS t2 ON t1.product_id = t2.product_id
WHERE t1.del_flag = 0 ORDER BY root_review_id;

CASE …. AS root_review_id の箇所では、親コメントなら自身のreview_id,子コメントなら親コメントのreview_idを取得して、このroot_review_id を利用してORDER BY しています。

このようにすることで、
コメントA
コメントAの返信a
コメントAの返信b
コメントAの返信c
コメントB



といった順番で取得できるようになりますので、あとはテンプレートループ内でparent_review_idの値によって親コメントか、子コメントかを判別して出力するといった形が最善でしょう。

<dl>
{section name=cnt loop=$arrReview}
    {if $arrReview[cnt].parent_review_id == null} {* 親コメント parent_review_idがnullかチェック *}
        <dt>親コメント</dt>
    {else}
        <dd>子コメント</dd>
    {/if}
{/section}
</dl>

更新

親コメントの書き込み時間が新しい順にSQLを修正してみます。

SQL

SELECT
  t1.review_id,
  t1.parent_review_id,
  t1.comment,
  t1.del_flag,
  t1.create_date,
  t1.product_id,
  t1.reviewer_name,
  t2.product_id,  
  t3.create_date, //親コメントの作成日時
  CASE WHEN t1.parent_review_id IS NULL THEN t1.review_id ELSE t1.parent_review_id END as root_review_id
FROM review AS t1
  LEFT JOIN product AS t2 ON t1.product_id = t2.product_id
  LEFT JOIN review as t3 ON ( CASE WHEN t1.parent_review_id IS NULL THEN t1.review_id ELSE t1.parent_review_id END ) = t3.review_id
WHERE t1.del_flag = 0 
ORDER BY t3.create_date DESC, t1.create_date ASC;

新たにLEFT JOIN句を追加しました。
これはparent_review_idを元に同じreviewテーブルをJOINし、親コメントの作成日時で並び替えを行っています。

並び替えの優先順序は

  1. 親コメントの作成日時(降順)
  2. 子コメントの作成日時(昇順)

これでご希望の動作になるかと思います。

回答者: Anonymous

Leave a Reply

Your email address will not be published. Required fields are marked *