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

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

ただいまの
回答率

87.49%

コメント返信のDB構造と表示方法

解決済

回答 2

投稿 編集

  • 評価
  • クリップ 2
  • VIEW 3,854

score 16

 環境

Laravel5.5
PHP7.2
MySQL5.7.23

 前提・実現したいこと

ひとつの記事に対しコメントをすることが出来、そのコメントに返信が出来るような機能を開発しています。
まさにyoutubeのようなコメント欄を作りたいです。
コメントに返信をすると一段下がったような表示になり、一定数のコメントがたまるとreadmoreが出てくるようなイメージです。

 DB構成

 Posts table

column type key comment
post_id int PRIMARY KEY 記事ID
post_body text 記事本文
post_user string uuid ユーザー
created_at timestamp 投稿日時

 Comments table

column type key comment
comment_id int RIMARY KEY コメントID
comment_body text コメント本文
comment_user string uuid ユーザー
parent_podt int FOREIGN KEY : posts(post_id) 親記事  
parent_comment int nullable 親コメント
created_at timestamp 投稿日時

記事に対してのコメントだった場合はparent_comment = nullとなります。
逆にコメントに対しての返信だった場合はparent_commentにコメントIDが入ります。

 ソースコード

//uuidなどは省略
$comments[
['comment_id'=>1,'comment_body'=>'aaa','parent_post'=>1,'parent_comment'=>null],
['comment_id'=>2,'comment_body'=>'bbb','parent_post'=>1,'parent_comment'=>null],
['comment_id'=>3,'comment_body'=>'ccc','parent_post'=>1,'parent_comment'=>1],
['comment_id'=>4,'comment_body'=>'ddd','parent_post'=>1,'parent_comment'=>1],
]

これを表示しやすいように加工するにはどうしたらいいでしょうか?
$comments->groupBy('parent_comment')を使ってみましたが、Viewでループを何度もまわさないと思ったように表示できませんでした。

$comments=$comments->groupBy('parent_comment');
$comments[
    "" =>[
        ['comment_id'=>1,'comment_body'=>'aaa','parent_post'=>1,'parent_comment'=>null],
        ['comment_id'=>2,'comment_body'=>'bbb','parent_post'=>1,'parent_comment'=>null],
    ],
    1 =>[
        ['comment_id'=>3,'comment_body'=>'ccc','parent_post'=>1,'parent_comment'=>1],
        ['comment_id'=>4,'comment_body'=>'ddd','parent_post'=>1,'parent_comment'=>1],
    ],
]

あいまいな質問になっていると思いますが、youtubeみたいなのコメント欄をLaravelで作るにはどうしたらいいか教えてください。
よろしくお願いします。

 余談

質問とは直接関係がなく申し訳ありませんが、ついでに質問させてください。
DBを作るときにvarchar 30などサイズを決めると思いますが、これは出来る限り指定したほうがいいのでしょうか?
参考となる記事などでも構いませんので、その理由も教えていただけると幸いです。

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

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

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

    クリップを取り消します

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

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

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

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

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

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

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

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

    質問の評価を下げる

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

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

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

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

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

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

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

    詳細な説明はこちら

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

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

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

質問への追記・修正、ベストアンサー選択の依頼

  • yambejp

    2018/11/01 14:17

    MySQLのバージョンも記載ください。string型ってchar型やvarchar型ではないのでしょうか?

    キャンセル

  • m.ts10806

    2018/11/01 14:20

    MySQLをタグに追加しておいてください

    キャンセル

  • baron3

    2018/11/01 18:21

    バージョン、タグ修正致しました。string型はchar型やvarchar型のことです。migrationファイルの認識で書いてしまったのでこちらも修正致しました。よろしくお願いします。

    キャンセル

回答 2

+1

親子関係が分岐していくモデルを想定しているのでしたら木構造を学習する必要があります。

親の情報だけもつものは隣接リストモデルといって、単純ですが取扱が面倒です。
参照の際は入れ子集合モデルというデータ管理をかませると一気に楽になります。
SQLで入れ子集合モデルを実現するにはサーバー側でプロシージャという仕組みで
変換をする必要があります。

投稿

  • 回答の評価を上げる

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

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

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

  • 回答の評価を下げる

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

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

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

check解決した方法

0

今回のケースではコメントに対して返信があった場合、そのコメントを親とすることでyoutubeと同じようなコメント欄が実現できました。
コメントテーブルとリプライテーブルでDB構成が似通る為、パフォーマンス等の問題があるようでしたらコメントで教えて頂ければ幸いです。

木構造のDB構成についてはこちらが参考になりました。yambejpさんヒントを与えてくださりありがとうございます。

 DB構成

 Posts table

column type key comment
post_id int PRIMARY KEY 記事ID
post_body text 記事本文
post_user string uuid ユーザー
created_at timestamp 投稿日時

 Comments table

column type key comment
comment_id int RIMARY KEY コメントID
comment_body text コメント本文
comment_user string uuid ユーザー
parent_podt int FOREIGN KEY : posts(post_id) 親記事  
created_at timestamp 投稿日時

 Replies table

column type key comment
reply_id int RIMARY KEY 返信ID
reply_body text 返信本文
reply_user string uuid ユーザー
reply_comment_parent int FOREIGN KEY : comments(comment_id) 親コメント  
created_at timestamp 投稿日時
@foreach ($comments as $comment)
<div class="media d-block d-md-flex mt-3">
    <div id="commentIDcar1" class="media-body text-center text-md-left ml-md-3 ml-0" data-comment="1">
        <div id="comment-body">
            <h5 id="parent1" class="font-weight-bold mt-0">
                <a href="#" class="userName">{{$comment->comment_user}}#{{$comment->comment_id}}</a>
                <a href="#" class="float-right replay">
                <i class="fa fa-reply"></i>
                </a>
            </h5>
                {!! nl2br(e($comment->comment_body)) !!}
        </div>
        @if(!is_null($comment->replies))
            @foreach ($comment->replies as $replay)
            <div class="media d-block d-md-flex mt-3">
                <div id="commentIDcar1" class="media-body text-center text-md-left ml-md-3 ml-0" data-comment="1">
                        <div id="comment-body">
                            <h5 id="parent1" class="font-weight-bold mt-0">
                                <a href="#" class="userName">{{$replay->reply_user}}#{{$replay->reply_id}}</a>
                                <a href="#" class="float-right replay">
                                <i class="fa fa-reply"></i>
                                </a>
                            </h5>
                                {!! nl2br(e($replay->reply_body)) !!}
                        </div>

                </div>
            </div>
            @endforeach
        @endif
    </div>
</div> 
@endforeach

投稿

編集

  • 回答の評価を上げる

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

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

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

  • 回答の評価を下げる

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

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

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

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

  • ただいまの回答率 87.49%
  • 質問をまとめることで、思考を整理して素早く解決
  • テンプレート機能で、簡単に質問をまとめられる

関連した質問

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