›
›
›
  1. docs
  2. ›
  3. byrcsc/laravel-comments
1.x
Browse documentationOpenClose

Getting started

  • Introduction
  • Installation and setup
  • Quick start

Core concepts

  • Commentable models
  • Threads and replies
  • Moderation
  • Initial status
  • Pinning
  • Reactions
  • Edits and revisions
  • Attachments
  • Deleting comments

Operations

  • Comment counts
  • Events and listeners
  • Reply notifications
  • Authorization
  • Rendering and safety

Reference

  • Configuration
  • Console commands
  • Testing
  • Troubleshooting

Getting started

  • Introduction
  • Installation and setup
  • Quick start

Core concepts

  • Commentable models
  • Threads and replies
  • Moderation
  • Initial status
  • Pinning
  • Reactions
  • Edits and revisions
  • Attachments
  • Deleting comments

Operations

  • Comment counts
  • Events and listeners
  • Reply notifications
  • Authorization
  • Rendering and safety

Reference

  • Configuration
  • Console commands
  • Testing
  • Troubleshooting

byrcsc/laravel-comments · 1.x

Threads and replies.

Build nested comment threads from parent relationships and depth limits.

A thread is a comment and everything hanging off its parent_id. Replies are ordinary comments with a parent, on the same commentable, carrying their own status, reactions, revisions, and attachments.

Reply to a comment

$reply = $comment->reply('Agreed, especially the last section.', by: $teammate);

$guestReply = $comment->replyAsGuest(
    'Same question here.',
    name: 'Jane',
    email: 'jane@example.com',
);

Both mirror the write methods on the commentable, and both take the parent's commentable_type and commentable_id automatically, a reply is always on the same record as the comment it answers.

Replying to an unsaved comment throws a LogicException. Persist the parent first.

Read a thread

Load thread starters with their replies, nesting to the depth your interface renders:

$threads = $post->comments()
    ->approved()
    ->topLevel()
    ->with('replies.replies')
    ->get();

replies is direct replies only. There is no recursive relation and no materialized path column: the package stores the parent key and leaves the shape of the query to you, because a two-level interface and a fully nested one want different things.

For a flat list, a moderation queue, an activity feed, skip topLevel() entirely and read every comment at once.

Ask how deep a comment sits

$comment->depth();  // 0 at the top, one more per level above

The walk follows parent up the chain, so it costs a query per level unless the parents are already loaded. It reads the chain rather than a stored column, which means it cannot disagree with the table.

The depth limit

comments.max_depth caps how deep replies nest. It defaults to 3, so a top-level comment sits at depth 0 and replies are allowed at depths 1, 2, and 3.

'max_depth' => 3,   // null for unlimited

Creating a reply below the limit throws a ThreadTooDeepException and stores nothing:

use ByRcsc\LaravelComments\Exceptions\ThreadTooDeepException;

try {
    $deep->reply('One level too far', by: $user);
} catch (ThreadTooDeepException $e) {
    // Nothing was written.
}

Two things about the limit are worth knowing before you change it.

It applies at creation only. Tightening the limit never reshapes existing threads: comments already deeper than the new value stay exactly where they are, and stay readable. Only new replies are refused.

It applies to every write path. The check runs on Eloquent's creating event, so factories and Comments::fake() are held to it as well as reply(). A test cannot build a thread the engine would refuse.

The body length limit

comments.max_length is the other creation-time gate, in characters:

'max_length' => 2_000,   // null for no limit beyond the column

Exceeding it throws a BodyTooLongException and stores nothing. Multibyte characters count as one, and nothing is ever silently truncated. The same check runs again on an edit, so an edit cannot do what a write was refused, see edits and revisions.

Threads and deletion

Soft deleting a comment leaves its replies readable under a tombstone: the parent is hidden by Eloquent's global scope, the children are not. Force deleting takes the whole subtree with it through the database's cascade on parent_id.

That asymmetry is deliberate, and it has consequences for events and counts. See deleting comments.

What to read next

  • Moderation to filter which thread entries visitors see.
  • Pinning to order selected comments before the rest.
  • Deletion to compare tombstones with subtree removal.
PreviousCommentable modelsNextModeration
View source

On this page

  1. Reply to a comment
  2. Read a thread
  3. Ask how deep a comment sits
  4. The depth limit
  5. The body length limit
  6. Threads and deletion
  7. What to read next