PHPackages                             anil/comments - PHPackages - PHPackages  [Skip to content](#main-content)[PHPackages](/)[Directory](/)[Categories](/categories)[Trending](/trending)[Leaderboard](/leaderboard)[Changelog](/changelog)[Analyze](/analyze)[Collections](/collections)[Log in](/login)[Sign up](/register)

1. [Directory](/)
2. /
3. [Database &amp; ORM](/categories/database)
4. /
5. anil/comments

ActiveLibrary[Database &amp; ORM](/categories/database)

anil/comments
=============

A Laravel package providing a full-featured, framework-agnostic commenting system for any Eloquent model.

v2.0.0(3mo ago)68.6k↑117.9%1MITPHPPHP ^8.2|^8.3|^8.4|^8.5CI passing

Since Apr 19Pushed 3mo agoCompare

[ Source](https://github.com/anilkumarthakur60/comments)[ Packagist](https://packagist.org/packages/anil/comments)[ RSS](/packages/anil-comments/feed)WikiDiscussions 2.x Synced 3d ago

READMEChangelog (3)Dependencies (20)Versions (7)Used By (0)

anil/comments
=============

[](#anilcomments)

A full-featured commenting system for Laravel. Attach comments to any Eloquent model with threaded replies, reactions, guest commenting, approval workflows, and a framework-agnostic UI — all in one package.

Features
--------

[](#features)

- Comment on any Eloquent model (polymorphic)
- Threaded replies with configurable nesting depth
- Reactions system (like/dislike, or any custom types)
- Guest commenting with honeypot spam protection
- Comment approval workflow
- Soft deletes (opt-in)
- Pagination (top-level comments)
- Rate limiting
- Authorization via Laravel gates/policies
- Events dispatched on create, update, and delete
- Framework-agnostic UI (no Bootstrap or Tailwind required)
- Gravatar avatars with color-coded initials fallback
- 13 supported locales
- Full REST API
- Support for multiple User models and non-integer IDs
- N+1 query optimized

Screenshots
-----------

[](#screenshots)

**Guest user** (guest commenting enabled — name and email fields shown):

[![Guest view](guest.png)](guest.png)

**Logged-in user** (comment form without guest fields, reply button visible):

[![Logged-in view](logged-in.png)](logged-in.png)

**Logged-out user** (guest commenting disabled — authentication prompt shown):

[![Logged-out view](logout.png)](logout.png)

Requirements
------------

[](#requirements)

- PHP 8.2+
- Laravel 11, 12, or 13

Installation
------------

[](#installation)

```
composer require anil/comments
php artisan migrate
```

Setup
-----

[](#setup)

### 1. Add `Commenter` trait to your User model

[](#1-add-commenter-trait-to-your-user-model)

```
use Anil\Comments\Commenter;

class User extends Authenticatable
{
    use Notifiable, Commenter;
}
```

### 2. Add `Commentable` trait to any model you want to comment on

[](#2-add-commentable-trait-to-any-model-you-want-to-comment-on)

```
use Anil\Comments\Commentable;

class Post extends Model
{
    use Commentable;
}
```

### 3. Render the comments component in your view

[](#3-render-the-comments-component-in-your-view)

```
@comments(['model' => $post])
```

That's it. The package auto-detects the authenticated user and renders the full comment UI.

Blade Component Options
-----------------------

[](#blade-component-options)

```
@comments([
    'model'                => $post,       // required — the commentable model
    'approved'             => true,        // show only approved comments (default: all)
    'perPage'              => 10,          // paginate top-level comments
    'maxIndentationLevel'  => 3,           // override max reply nesting (default: config value)
    'reactionsEnabled'     => true,        // override config
    'reactionTypes'        => ['like', 'dislike'], // override config
    'sort'                 => 'latest',    // 'latest' or 'oldest'
])
```

### Pagination

[](#pagination)

Pagination applies to top-level comments only. A parent comment and all of its replies count as one "page unit" — so `perPage => 2` shows two parent comments plus all their children.

### Nesting depth

[](#nesting-depth)

By default replies nest up to level 3:

```
- 0
    - 1
        - 2
            - 3

```

Replies beyond the max depth are shown at the deepest level. Override per-component with `maxIndentationLevel` or globally via config (`max_depth`).

Configuration
-------------

[](#configuration)

Publish the config file:

```
php artisan vendor:publish --provider="Anil\Comments\ServiceProvider" --tag=config
```

Key options in `config/comments.php`:

KeyDefaultDescription`model``Comment::class`Custom Comment model`reaction_model``CommentReaction::class`Custom reaction model`controller``WebCommentController::class`Custom controller`routes``true`Register package routes`load_migrations``true`Auto-load package migrations`approval_required``false`Require admin approval before comments are visible`guest_commenting``true`Allow unauthenticated users to comment`soft_deletes``false`Use soft deletes instead of hard deletes`max_depth``3`Maximum reply nesting level`sort``'latest'`Default comment sort (`'latest'` or `'oldest'`)`reactions.enabled``true`Enable the reactions system`reactions.types``['like', 'dislike']`Allowed reaction types`rate_limiting.enabled``true`Enable rate limiting on comment submission`rate_limiting.max_attempts``10`Max submissions per window`rate_limiting.decay_minutes``1`Rate limit window in minutes`middleware``['web']`Middleware applied to comment routes`permissions`ArrayGate → policy method mappings`validation.*`ArrayOverride validation rules for each action`response_status`ArrayHTTP status codes for create/update/delete`response_messages`ArrayResponse message stringsPublishing Assets
-----------------

[](#publishing-assets)

```
# Views
php artisan vendor:publish --provider="Anil\Comments\ServiceProvider" --tag=views

# Migrations
php artisan vendor:publish --provider="Anil\Comments\ServiceProvider" --tag=migrations

# Translations
php artisan vendor:publish --provider="Anil\Comments\ServiceProvider" --tag=translations

# All at once
php artisan vendor:publish --provider="Anil\Comments\ServiceProvider" --tag=comments
```

Authorization
-------------

[](#authorization)

The package registers Laravel gates backed by `CommentPolicy`:

GateDefault rule`create-comment`Any authenticated user`edit-comment`Comment author only`delete-comment`Comment author or user with `is_admin = true``reply-to-comment`Any authenticated user (cannot reply to own comment)You can override the gate-to-policy mappings in `config/comments.php` under `permissions`, or publish and modify `CommentPolicy` directly.

Reactions
---------

[](#reactions)

Reactions are enabled by default. Each user can have one reaction per comment. Sending the same reaction type again removes it (toggle). Sending a different type switches it.

Configure types in `config/comments.php`:

```
'reactions' => [
    'enabled' => true,
    'types'   => ['like', 'dislike'],
],
```

Any string values are valid reaction types.

Guest Commenting
----------------

[](#guest-commenting)

When `guest_commenting` is enabled, unauthenticated users can submit comments with a `guest_name` and `guest_email`. Honeypot spam protection (via `spatie/laravel-honeypot`) is automatically applied.

Disable guest commenting to show a login prompt instead:

```
'guest_commenting' => false,
```

Events
------

[](#events)

The package dispatches the following events (all implement `SerializesModels` for queued listeners):

EventFired when`Anil\Comments\Events\CommentCreated`A comment is created`Anil\Comments\Events\CommentUpdated`A comment is edited`Anil\Comments\Events\CommentDeleted`A comment is deletedRegister listeners in your `EventServiceProvider` as normal.

REST API
--------

[](#rest-api)

All routes are prefixed with `/comments` and named with `comments.*`.

MethodURINameDescriptionPOST`/comments``comments.store`Create a commentPUT`/comments/{comment}``comments.update`Edit a commentDELETE`/comments/{comment}``comments.destroy`Delete a commentPOST`/comments/{comment}``comments.reply`Reply to a commentPOST`/comments/{comment}/react``comments.react`Toggle a reaction### POST `/comments`

[](#post-comments)

```
{
  "commentable_type": "App\\Models\\Post",
  "commentable_id": "1",
  "message": "Great post!"
}
```

Guest fields (required when unauthenticated and guest commenting is enabled):

```
{
  "guest_name": "Jane Doe",
  "guest_email": "jane@example.com"
}
```

### PUT `/comments/{comment}`

[](#put-commentscomment)

```
{
  "message": "Updated comment text."
}
```

### POST `/comments/{comment}` (reply)

[](#post-commentscomment-reply)

```
{
  "message": "Reply text."
}
```

### POST `/comments/{comment}/react`

[](#post-commentscommentreact)

```
{
  "type": "like"
}
```

Returns:

```
{
  "reaction_counts": { "like": 3, "dislike": 1 },
  "user_reaction": "like"
}
```

Queryable Methods (Commentable trait)
-------------------------------------

[](#queryable-methods-commentable-trait)

These methods are available on any model using the `Commentable` trait:

```
$post->comments();                                // all comments
$post->approvedComments();                        // only approved
$post->latestComments(5);                         // 5 most recent
$post->commentsWithReplies();                     // top-level + eager-loaded replies
$post->totalComments();                           // count
$post->commentsByUser($userId, $commenterType);   // filter by user
$post->commentsInDateRange($start, $end);         // date range
$post->commentsWithAttributes(['approved' => true]);
$post->commentsWithRelations(['commenter']);

Post::mostCommented(5);                           // static — top 5 most commented
```

Lifecycle Hooks
---------------

[](#lifecycle-hooks)

You can define these methods on your **Comment model** (after publishing and extending) or on your **commentable model** to run custom logic around comment operations:

MethodTrigger`afterCreate()`After a comment is created`afterUpdate()`After a comment is updated`beforeDelete()`Before a comment is deleted`afterDelete()`After a comment is deleted`afterReply()`After a reply is createdThe service layer calls these hooks when they exist — no base implementation is required.

Localization
------------

[](#localization)

The package ships with translations for 13 locales:

`ar`, `ca`, `de`, `en`, `es`, `fr`, `in`, `it`, `ja`, `nl`, `np`, `pt`, `ru`

Publish translations to customize or add new locales:

```
php artisan vendor:publish --provider="Anil\Comments\ServiceProvider" --tag=translations
```

Custom Controller
-----------------

[](#custom-controller)

To extend or replace the controller, set the `controller` key in config:

```
'controller' => \App\Http\Controllers\MyCommentController::class,
```

Your controller must implement `Anil\Comments\CommentControllerInterface` or extend `Anil\Comments\CommentController`.

License
-------

[](#license)

MIT — see [LICENSE](https://opensource.org/licenses/MIT).

###  Health Score

50

—

FairBetter than 95% of packages

Maintenance81

Actively maintained with recent releases

Popularity29

Limited adoption so far

Community9

Small or concentrated contributor base

Maturity67

Established project with proven stability

 Bus Factor1

Top contributor holds 94.3% of commits — single point of failure

How is this calculated?**Maintenance (25%)** — Last commit recency, latest release date, and issue-to-star ratio. Uses a 2-year decay window.

**Popularity (30%)** — Total and monthly downloads, GitHub stars, and forks. Logarithmic scaling prevents top-heavy scores.

**Community (15%)** — Contributors, dependents, forks, watchers, and maintainers. Measures real ecosystem engagement.

**Maturity (30%)** — Project age, version count, PHP version support, and release stability.

###  Release Activity

Cadence

Every ~268 days

Total

5

Last Release

101d ago

Major Versions

v1.0.1 → 2.x-dev2026-03-25

### Community

Maintainers

![](https://avatars.githubusercontent.com/u/16583802?v=4)[Er. Anil Kumar Thakur](/maintainers/anilkumarthakur60)[@anilkumarthakur60](https://github.com/anilkumarthakur60)

---

Top Contributors

[![anilkumarthakur60](https://avatars.githubusercontent.com/u/16583802?v=4)](https://github.com/anilkumarthakur60 "anilkumarthakur60 (50 commits)")[![StyleCIBot](https://avatars.githubusercontent.com/u/11048387?v=4)](https://github.com/StyleCIBot "StyleCIBot (3 commits)")

---

Tags

laraveleloquentcommentsreactionspolymorphiccommentingthreaded-comments

###  Code Quality

TestsPest

Static AnalysisPHPStan

Code StyleLaravel Pint

### Embed Badge

![Health badge](/badges/anil-comments/health.svg)

```
[![Health](https://phpackages.com/badges/anil-comments/health.svg)](https://phpackages.com/packages/anil-comments)
```

###  Alternatives

[psalm/plugin-laravel

Psalm plugin for Laravel

3355.3M346](/packages/psalm-plugin-laravel)[api-platform/laravel

API Platform support for Laravel

58171.6k14](/packages/api-platform-laravel)[roots/acorn

Framework for Roots WordPress projects built with Laravel components.

9762.4M131](/packages/roots-acorn)[laravel/cashier

Laravel Cashier provides an expressive, fluent interface to Stripe's subscription billing services.

2.6k29.9M148](/packages/laravel-cashier)[laravel/scout

Laravel Scout provides a driver based solution to searching your Eloquent models.

1.7k55.0M618](/packages/laravel-scout)[laravel/pulse

Laravel Pulse is a real-time application performance monitoring tool and dashboard for your Laravel application.

1.7k15.1M132](/packages/laravel-pulse)

PHPackages © 2026

[Directory](/)[Categories](/categories)[Trending](/trending)[Changelog](/changelog)[Analyze](/analyze)
