PHPackages                             kirschbaum-development/commentions - 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. [Utility &amp; Helpers](/categories/utility)
4. /
5. kirschbaum-development/commentions

ActiveLibrary[Utility &amp; Helpers](/categories/utility)

kirschbaum-development/commentions
==================================

A package to allow you to create comments, tag users and more

0.7.10(5mo ago)151159.6k—2.5%35[7 issues](https://github.com/kirschbaum-development/commentions/issues)[4 PRs](https://github.com/kirschbaum-development/commentions/pulls)MITPHPCI passing

Since Jan 30Pushed 2w ago13 watchersCompare

[ Source](https://github.com/kirschbaum-development/commentions)[ Packagist](https://packagist.org/packages/kirschbaum-development/commentions)[ RSS](/packages/kirschbaum-development-commentions/feed)WikiDiscussions main Synced 1w ago

READMEChangelog (10)Dependencies (32)Versions (47)Used By (0)

[![](screenshots/commentions-logo.png)](screenshots/commentions-logo.png)

[![Laravel Supported Versions](https://camo.githubusercontent.com/aeacaa9b8ca97245b5b52255479d4e4863dd084a32a9f478a3f22bfdb31295d6/68747470733a2f2f696d672e736869656c64732e696f2f62616467652f6c61726176656c2d31302e782f31312e782f31322e782f31332e782d677265656e2e737667)](https://camo.githubusercontent.com/aeacaa9b8ca97245b5b52255479d4e4863dd084a32a9f478a3f22bfdb31295d6/68747470733a2f2f696d672e736869656c64732e696f2f62616467652f6c61726176656c2d31302e782f31312e782f31322e782f31332e782d677265656e2e737667)[![Filament Supported Versions](https://camo.githubusercontent.com/7a1931b4d7b455c7c003c9b8c5c0f9f01e3637cb7df8c56c9257e030cec8d89c/68747470733a2f2f696d672e736869656c64732e696f2f62616467652f66696c616d656e742d332e782f342e782f352e782d677265656e2e737667)](https://camo.githubusercontent.com/7a1931b4d7b455c7c003c9b8c5c0f9f01e3637cb7df8c56c9257e030cec8d89c/68747470733a2f2f696d672e736869656c64732e696f2f62616467652f66696c616d656e742d332e782f342e782f352e782d677265656e2e737667)[![CI](https://github.com/kirschbaum-development/commentions/actions/workflows/ci.yml/badge.svg)](https://github.com/kirschbaum-development/commentions/actions/workflows/ci.yml)[![MIT Licensed](https://camo.githubusercontent.com/55c0218c8f8009f06ad4ddae837ddd05301481fcf0dff8e0ed9dadda8780713e/68747470733a2f2f696d672e736869656c64732e696f2f62616467652f6c6963656e73652d4d49542d627269676874677265656e2e7376673f7374796c653d666c61742d737175617265)](LICENSE.md)[![Latest Version on Packagist](https://camo.githubusercontent.com/e176550a612c0259985b5bf7295be3e9ea6d3d5039bbdfffde97679bb2fb970a/68747470733a2f2f696d672e736869656c64732e696f2f7061636b61676973742f762f6b69727363686261756d2d646576656c6f706d656e742f636f6d6d656e74696f6e732e7376673f7374796c653d666c61742d737175617265)](https://packagist.org/packages/kirschbaum-development/commentions)[![Total Downloads](https://camo.githubusercontent.com/5f24f2acaa414e0c5e3a073b69c6b5f419db6fd3b31ff869bcd8a16e2c6f37da/68747470733a2f2f696d672e736869656c64732e696f2f7061636b61676973742f64742f6b69727363686261756d2d646576656c6f706d656e742f636f6d6d656e74696f6e732e7376673f7374796c653d666c61742d737175617265)](https://packagist.org/packages/kirschbaum-development/commentions)

Commentions is a drop-in package for Filament that allows you to add comments to your resources. You can configure it so your users are mentionable in the comments, and it dispatches events so you can handle mentions in your own application however you like.

[![](screenshots/comments-demo.png)](screenshots/comments-demo.png)

- [Installation](#installation)
- [Usage](#usage)
- [Upgrading](#upgrading)
- [Security](#security)
- [Credits](#credits)
- [Sponsorship](#sponsorship)
- [License](#license)

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

[](#installation)

1. Install the package via Composer:

```
composer require kirschbaum-development/commentions
```

2. Run the installer

```
php artisan commentions:install
```

Usage
-----

[](#usage)

1. Register the assets

```
php artisan filament:assets
```

2. In your `User` model implement the `Commenter` interface.

```
use Kirschbaum\Commentions\Contracts\Commenter;

class User extends Model implements Commenter
{
    // ...
}
```

3. In the model you want to add comments, implement the `Commentable` interface and the `HasComments` trait.

```
use Kirschbaum\Commentions\HasComments;
use Kirschbaum\Commentions\Contracts\Commentable;

class Project extends Model implements Commentable
{
    use HasComments;
}
```

### Usage with Filament

[](#usage-with-filament)

There are a couple of ways to use Commentions with Filament.

1. Register the component in your Filament Infolists:

> This works for Filament 3 and 4.

```
    CommentsEntry::make('comments')
        ->mentionables(fn (Model $record) => User::all()),
```

If you wish to make the comments more distinct from the rest of the page, we recommend wrapping them in a `Section`.

For Filament 3:

```
\Filament\Infolists\Components\Section::make('Comments')
    ->schema([
        CommentsEntry::make('comments')
            ->mentionables(fn (Model $record) => User::all()),
    ]),
```

For Filament 4:

```
\Filament\Schemas\Components\Section::make('Comments')
    ->components([
        CommentsEntry::make('comments')
            ->mentionables(fn (Model $record) => User::all()),
    ]),
```

2. Or in your table actions:

If you are using Filament 3, you must use `CommentsTableAction` in your table's `actions` array:

```
use Kirschbaum\Commentions\Filament\Actions\CommentsTableAction;

->actions([
    CommentsTableAction::make()
        ->mentionables(User::all())
])
```

If you are using Filament 4, you should use `CommentsAction` in `recordActions` instead:

```
use Kirschbaum\Commentions\Filament\Actions\CommentsAction;

->recordActions([
    CommentsAction::make()
        ->mentionables(User::all())
])
```

3. Or as a header action:

> This works for Filament 3 and 4.

```
use Kirschbaum\Commentions\Filament\Actions\CommentsAction;

protected function getHeaderActions(): array
{
    return [
        CommentsAction::make()
            ->mentionables(User::all()),
    ];
}
```

4. Or directly in form schemas for Edit pages (Filament 4):

```
use Filament\Forms\Components\ViewField;

public static function configure(Schema $schema): Schema
{
    return $schema
        ->components([
            // Your other form fields...

            ViewField::make('comments_section')
                ->view('...') // View file
                ->viewData(fn ($livewire) => [
                    'record' => $livewire->record ?? null
                ])
                ->columnSpanFull()
                ->hiddenLabel(),
        ]);
}
```

View file contents

Filament 3:

```
@livewire('commentions::comments', [
    'record' => $record,
    'mentionables' => \App\Models\User::all(),
    'readonly' => $readonly ?? false
])
```

Filament 4:

```
@livewire('commentions.comments', [
    'record' => $record,
    'mentionables' => \App\Models\User::all(),
    'readonly' => $readonly ?? false
])
```

To make the form comments readonly, pass the `readonly` flag in the viewData:

```
ViewField::make('comments_section')
    ->view('...') // View file
    ->viewData(fn ($livewire) => [
        'record' => $livewire->record ?? null,
        'readonly' => true, // Enable readonly mode
    ])
    ->columnSpanFull()
    ->hiddenLabel(),
```

**Note:** For View pages, continue using the infolist approach (option 1) as it works perfectly in that context.

### Readonly Mode

[](#readonly-mode)

You can make comments readonly by chaining the `readonly()` method on the action. In readonly mode:

- Users cannot add new comments
- Users cannot edit existing comments
- Users cannot delete comments
- Users cannot react to comments (reactions are displayed but not interactive)

```
// Make comments readonly
CommentsEntry::make()
    ->readonly()
    ->mentionables(User::all())

CommentsAction::make()
    ->readonly()
    ->mentionables(User::all())

CommentsTableAction::make()
    ->readonly()
    ->mentionables(User::all())

// You can also conditionally enable readonly mode
CommentsAction::make()
    ->readonly(auth()->user()->cannot('create', Comment::class))
    ->mentionables(User::all())
```

This is useful for scenarios like:

- Archived or closed records where no further comments should be allowed
- View-only access for certain user roles
- Historical comment viewing
- Audit trails where comments should be preserved but not modified

### Subscription Management

[](#subscription-management)

Commentions includes a subscription system that allows users to subscribe to receive notifications when new comments are added to a commentable resource.

#### Subscription Actions

[](#subscription-actions)

You can add subscription actions to your Filament resources:

```
use Kirschbaum\Commentions\Filament\Actions\SubscriptionAction;

// In header actions
protected function getHeaderActions(): array
{
    return [
        SubscriptionAction::make(),
    ];
}

// In table actions (Filament 3)
->actions([
    SubscriptionTableAction::make(),
])

// In record actions (Filament 4)
->recordActions([
    SubscriptionAction::make(),
])
```

#### Subscription Sidebar

[](#subscription-sidebar)

When using comments in modals, a subscription sidebar is automatically displayed showing:

- Subscribe/unsubscribe button for the current user
- List of users currently subscribed to the commentable
- Real-time updates when subscription status changes

##### Livewire options

[](#livewire-options)

When using the `commentions::comments` Livewire component directly, you can control the sidebar and its contents via component properties:

- `sidebarEnabled` (bool, default: true): toggles the entire subscription sidebar
- `showSubscribers` (bool, default: `config('commentions.subscriptions.show_subscribers', true)`): toggles the subscribers list within the sidebar

Examples:

For Livewire 3:

```
// Hide the sidebar entirely

// Keep the sidebar, but hide the subscribers list (uses config default if omitted)

```

For Livewire 4:

```
// Hide the sidebar entirely

// Keep the sidebar, but hide the subscribers list (uses config default if omitted)

```

Inside the component/template you can also rely on these computed properties:

- `canSubscribe`: whether the current user can subscribe
- `isSubscribed`: whether the current user is subscribed to the current record
- `subscribers`: a collection of current subscribers

The component exposes a `toggleSubscription()` action which subscribes/unsubscribes the current user.

#### Disabling the Subscription Sidebar

[](#disabling-the-subscription-sidebar)

You can disable the subscription sidebar if you don't want subscription functionality:

```
use Kirschbaum\Commentions\Filament\Actions\CommentsAction;

->recordActions([
    CommentsAction::make()
        ->mentionables(User::all())
        ->disableSidebar()
])
```

#### Subscription Methods

[](#subscription-methods)

The `HasComments` trait provides methods for managing subscriptions programmatically:

```
// Subscribe a user
$commentable->subscribe($user);

// Unsubscribe a user
$commentable->unsubscribe($user);

// Check if a user is subscribed
$isSubscribed = $commentable->isSubscribed($user);

// Get all subscribers
$subscribers = $commentable->getSubscribers();
```

---

### Configuration

[](#configuration)

You can publish the configuration file to make changes.

```
php artisan vendor:publish --tag="commentions-config"
```

#### Pagination (Filament)

[](#pagination-filament)

Commentions supports built-in pagination for the embedded list of comments and it is enabled by default. You can disable it or control the number of comments shown per page and per click.

- Enabled by default
- Disable via `disablePagination()`
- Configure page size
- Customize the load more label
- Control how many comments are appended per click (defaults to the page size)

Examples:

Default Usage:

```
use Kirschbaum\Commentions\Filament\Actions\CommentsAction;

->recordActions([
    CommentsAction::make()
        ->mentionables(User::all())
        ->perPage(10)

])
```

Without Pagination:

```
use Kirschbaum\Commentions\Filament\Actions\CommentsAction;

->recordActions([
    CommentsAction::make()
        ->mentionables(User::all())
        ->disablePagination();

])
```

Advanced Usage:

```
use Kirschbaum\Commentions\Filament\Infolists\Components\CommentsEntry;

Infolists\Components\Section::make('Comments')
    ->schema([
        CommentsEntry::make('comments')
            ->mentionables(fn (Model $record) => User::all())
            ->perPage(8)
            ->loadMoreIncrementsBy(8)
            ->loadMoreLabel('Show older'),
    ])
```

When pagination is enabled, a "Show more" button is displayed to load additional comments incrementally.

#### Configuring the User model and the mentionables

[](#configuring-the-user-model-and-the-mentionables)

If your `User` model lives in a different namespace than `App\Models\User`, you can configure it in `config/commentions.php`:

```
    'commenter' => [
        'model' => \App\Domains\Users\User::class,
    ],
```

#### Configuring the Comment model

[](#configuring-the-comment-model)

If you need to customize the Comment model, you can extend the `\Kirschbaum\Commentions\Comment` class and then update the `comment.model` option in your `config/commentions.php` file:

```
    'comment' => [
        'model' => \App\Models\Comment::class,
        // ...
    ],
```

#### Configuring Comment permissions

[](#configuring-comment-permissions)

By default, users can create comments, as well as edit and delete their own comments. You can adjust these permissions by implementing your own policy:

1. Create a custom policy

```
namespace App\Policies;

use Kirschbaum\Commentions\Comment;
use Kirschbaum\Commentions\Contracts\Commenter;
use Kirschbaum\Commentions\Policies\CommentPolicy as CommentionsPolicy;

class CommentPolicy extends CommentionsPolicy
{
    public function create(Commenter $user): bool
    {
        // TODO: Implement custom permission logic.
    }

    public function update($user, Comment $comment): bool
    {
        // TODO: Implement custom permission logic.
    }

    public function delete($user, Comment $comment): bool
    {
        // TODO: Implement custom permission logic.
    }
}
```

2. Register your policy in the configuration file

Update the `comment.policy` option in your `config/commentions.php` file:

```
    'comment' => [
        // ...
        'policy' => \App\Policies\CommentPolicy::class,
    ],
```

#### Configuring the Commenter name

[](#configuring-the-commenter-name)

By default, the `name` property will be used to render the mention names. You can customize it either by implementing the Filament `HasName` interface OR by implementing the optional `getCommenterName` method.

```
use Filament\Models\Contracts\HasName;
use Kirschbaum\Commentions\Contracts\Commenter;

class User extends Model implements Commenter, HasName
{
    public function getFilamentName(): string
    {
        return (string) '#' . $this->id . ' - ' . $this->name;
    }
}
```

```
use Kirschbaum\Commentions\Contracts\Commenter;

class User extends Model implements Commenter
{
    public function getCommenterName(): string
    {
        return (string) '#' . $this->id . ' - ' . $this->name;
    }
}
```

#### Configuring Reactions

[](#configuring-reactions)

By default, Commentions ships with the following reactions: `['👍', '❤️', '😂', '😮', '😢', '🤔']`. You can customize which reactions are available by updating the `reactions.allowed` option in your `config/commentions.php` file:

```
    'reactions' => [
        'allowed' => ['👍', '❤️', '😂', '🎉', '👀'],
    ],
```

#### Configuring the Commenter avatar

[](#configuring-the-commenter-avatar)

To configure the avatar, make sure your User model implements Filament's `HasAvatar` interface.

```
use Filament\Models\Contracts\HasAvatar;

class User extends Authenticatable implements Commenter, HasName, HasAvatar
{
    public function getFilamentAvatarUrl(): ?string
    {
        return $this->avatar_url;
    }
}
```

If your users do not implement `HasAvatar`, Commentions will consult an avatar provider before falling back to `ui-avatars.com`. By default it uses the current Filament panel's default provider (set via `Panel::defaultAvatarProvider(...)`). To force a specific provider regardless of panel context, set the `avatar_provider` config key:

```
// config/commentions.php
use Filament\AvatarProviders\GravatarProvider;

return [
    // ...
    'avatar_provider' => GravatarProvider::class,
];
```

Any class exposing a `get(Model|Authenticatable $user): string` method works.

#### Configuring Custom Actions

[](#configuring-custom-actions)

Add additional actions next to edit/delete:

```
use Kirschbaum\Commentions\Config;
use Filament\Actions\Action;

Config::registerCommentActions(fn ($comment) => Action::make('activityLogs')
    ->icon('heroicon-s-clock')
    ->iconButton()
    ->modalContent(/* ... */)
);
```

#### Configuring Comment Ratings

[](#configuring-comment-ratings)

Commentions can attach an optional star rating to a comment, review-style. Ratings are **disabled by default**.

Enable them globally in your `config/commentions.php` file (or via the matching environment variables):

```
    'ratings' => [
        'enabled' => env('COMMENTIONS_RATINGS_ENABLED', false),

        'max' => (int) env('COMMENTIONS_RATINGS_MAX', 5),
    ],
```

You can also enable ratings per component, which overrides the global config. This works on `CommentsEntry`, `CommentsAction`, and `CommentsTableAction`:

```
CommentsEntry::make('comments')
    ->mentionables(fn (Model $record) => User::all())
    ->enableRatings()
    ->maxRating(10)
```

Available methods:

- `enableRatings(bool|Closure $condition = true)` — enable the rating input for this component.
- `disableRatings()` — disable the rating input, even if enabled globally.
- `maxRating(int|Closure $max)` — set the highest selectable rating (defaults to `ratings.max`).

When ratings are enabled, commenters can pick a rating while writing or editing a comment, and each rated comment renders its score as filled stars. The rating is stored in a nullable `rating` column added by the package's `add_rating_to_commentions_comments_table` migration.

#### Configuring Attachments

[](#configuring-attachments)

Commentions can let users attach files to their comments. Attachments are **disabled by default**.

Enable attachments globally in `config/commentions.php` (or via the `COMMENTIONS_ATTACHMENTS_ENABLED` env variable):

```
    'attachments' => [
        'enabled' => env('COMMENTIONS_ATTACHMENTS_ENABLED', false),

        // Filesystem disk and directory used to store uploads.
        'disk' => env('COMMENTIONS_ATTACHMENTS_DISK', 'public'),
        'directory' => env('COMMENTIONS_ATTACHMENTS_DIRECTORY', 'commentions-attachments'),

        // Maximum size per file, in kilobytes.
        'max_size' => (int) env('COMMENTIONS_ATTACHMENTS_MAX_SIZE', 10240),

        // Maximum number of files per comment.
        'max_files' => (int) env('COMMENTIONS_ATTACHMENTS_MAX_FILES', 5),

        // Accepted MIME types, validated against the file's actual contents.
        'accepted_mime_types' => [
            'image/jpeg', 'image/png', 'image/gif', 'image/webp', 'application/pdf',
            // ...
        ],
    ],
```

You can also toggle attachments per component instead of globally, which overrides the config value:

```
use Kirschbaum\Commentions\Filament\Infolists\Components\CommentsEntry;

CommentsEntry::make('comments')->mentionables(User::all())->enableAttachments();
CommentsEntry::make('comments')->mentionables(User::all())->enableAttachments(fn () => auth()->user()->isAdmin());
CommentsEntry::make('comments')->mentionables(User::all())->disableAttachments();
```

The same `enableAttachments()` / `disableAttachments()` methods are available on `CommentsAction` and `CommentsTableAction`.

Warning

`accepted_mime_types` ships with a safe set of image types and file types. Leaving it empty allows **any** file type, which is dangerous on a `public` disk. Types that browsers execute in-origin (such as `image/svg+xml` or `text/html`) would be served directly from your application's URL and could be used for stored XSS. Keep an explicit allowlist, or store attachments on a private disk.

Attachments are deleted from both the database and the underlying disk when their parent comment is deleted through the model (`$comment->delete()`).

#### Customizing TipTap Editor

[](#customizing-tiptap-editor)

1. Style

You can customize the TipTap editor CSS classes used using the `Config` class.

```
use Kirschbaum\Commentions\Config;

Config::resolveTipTapCssClassesUsing(function () {
    return 'prose max-w-none focus:outline-none p-4';
});
```

And you can also override the classes on a per-component basis using the `tipTapCssClasses()` method:

```
use Kirschbaum\Commentions\Filament\Infolists\Components\CommentsEntry;

CommentsEntry::make('comments')
    ->mentionables(fn (Model $record) => User::all())
    ->tipTapCssClasses('prose max-w-none focus:outline-none p-4')
```

Or with actions:

```
use Kirschbaum\Commentions\Filament\Actions\CommentsAction;

CommentsAction::make()
    ->mentionables(User::all())
    ->tipTapCssClasses('prose max-w-none focus:outline-none p-4')
```

**Important**: Make sure to whitelist the classes in your Tailwind config if you override them.

2. Toolbar

The comment editor shows a formatting toolbar above the input. The available buttons are:

`bold`, `italic`, `underline`, `strike`, `h1`, `h2`, `h3`, `blockquote`, `bulletList`, `orderedList`, `code`, `link`.

You can configure which buttons appear globally via the `toolbar` option in your `config/commentions.php` file. Buttons may be a flat list, or grouped into arrays to render visual separators between groups:

```
    'toolbar' => [
        'enabled' => env('COMMENTIONS_TOOLBAR_ENABLED', true),

        'buttons' => [
            ['bold', 'italic', 'underline'],
            ['bulletList', 'orderedList'],
            ['link'],
        ],
    ],
```

To hide the toolbar entirely, set `enabled` to `false` (or set `COMMENTIONS_TOOLBAR_ENABLED=false` in your `.env`).

You can also override the buttons on a per-component basis using the `toolbarButtons()` method:

```
use Kirschbaum\Commentions\Filament\Infolists\Components\CommentsEntry;

CommentsEntry::make('comments')
    ->mentionables(fn (Model $record) => User::all())
    ->toolbarButtons([['bold', 'italic'], ['link']])
```

Or with actions:

```
use Kirschbaum\Commentions\Filament\Actions\CommentsAction;

CommentsAction::make()
    ->mentionables(User::all())
    ->toolbarButtons(['bold', 'italic', 'link'])
```

Pass an empty array (`->toolbarButtons([])`) to hide the toolbar for a single component.

### Translations

[](#translations)

You can publish the package translation files and override any strings used by the UI.

Publish the language files into your application:

```
php artisan vendor:publish --tag="commentions-lang"
``

This will copy the language files to:

- `lang/vendor/commentions/{locale}/comments.php`

Override only the keys you need. Example (English):

```php
// lang/vendor/commentions/en/comments.php
return [
    'label' => 'Notes',
    'no_comments_yet' => 'No notes yet.',
    'add_reaction' => 'Add a reaction',
    'cancel' => 'Close',
    'delete' => 'Remove',
    'save' => 'Update',
];
```

### Events

[](#events)

Events are dispatched when a comment is created, reacted to, or when users are mentioned or subscribed:

- `Kirschbaum\Commentions\Events\UserWasMentionedEvent`
- `Kirschbaum\Commentions\Events\UserIsSubscribedToCommentableEvent`
- `Kirschbaum\Commentions\Events\CommentWasCreatedEvent`
- `Kirschbaum\Commentions\Events\CommentWasReactedEvent`

#### Subscription Events

[](#subscription-events)

When a new comment is created, all subscribed users receive notifications through the `UserIsSubscribedToCommentableEvent`. You can listen to this event to send custom notifications:

```
namespace App\Listeners;

use Illuminate\Queue\InteractsWithQueue;
use Illuminate\Contracts\Queue\ShouldQueue;
use App\Notifications\NewCommentNotification;
use Kirschbaum\Commentions\Events\UserIsSubscribedToCommentableEvent;

class SendSubscribedUserNotification implements ShouldQueue
{
    use InteractsWithQueue;

    public function handle(UserIsSubscribedToCommentableEvent $event): void
    {
        $event->user->notify(
            new NewCommentNotification($event->comment)
        );
    }
}
```

### Sending notifications when a user is mentioned

[](#sending-notifications-when-a-user-is-mentioned)

Every time a user is mentioned, the `Kirschbaum\Commentions\Events\UserWasMentionedEvent` is dispatched. Commentions ships an optional, opt-in notification you can enable via configuration, or you can listen to the event and handle it yourself.

Example usage:

```
namespace App\Listeners;

use Illuminate\Queue\InteractsWithQueue;
use Illuminate\Contracts\Queue\ShouldQueue;
use App\Notifications\UserMentionedInCommentNotification;
use Kirschbaum\Commentions\Events\UserWasMentionedEvent;

class SendUserMentionedNotification implements ShouldQueue
{
    use InteractsWithQueue;

    public function handle(UserWasMentionedEvent $event): void
    {
        $event->user->notify(
            new UserMentionedInCommentNotification($event->comment)
        );
    }
}
```

If you have [event auto-discovery](https://laravel.com/docs/11.x/events#registering-events-and-listeners), this should be enough. Otherwise, make sure to register your listener on the `EventServiceProvider`.

#### Built-in opt-in notifications

[](#built-in-opt-in-notifications)

Enable notifications for mentions in your `config/commentions.php`:

```
    'notifications' => [
        'mentions' => [
            'enabled' => true,
            'channels' => ['mail', 'database'],
        ],
    ],
```

Optionally, provide a URL resolver so emails/links point users to the right place:

```
use Kirschbaum\Commentions\Config;

Config::resolveCommentUrlUsing(function (\Kirschbaum\Commentions\Comment $comment) {
    // Return a URL to view the record and scroll to the comment
    return route('projects.show', $comment->commentable) . '#comment-' . $comment->getId();
});
```

### Resolving the authenticated user

[](#resolving-the-authenticated-user)

By default, when a new comment is made, the `Commenter` is automatically set to the current user logged in user (`auth()->user()`). If you want to change this behavior, you can implement your own resolver:

```
use Kirschbaum\Commentions\Config;

Config::resolveAuthenticatedUserUsing(
    fn () => auth()->guard('my-guard')->user()
)
```

### Getting the mentioned Commenters from an existing comment

[](#getting-the-mentioned-commenters-from-an-existing-comment)

```
$comment->getMentioned()->each(function (Commenter $commenter) {
    // do something with $commenter...
});
```

### Polling for new comments

[](#polling-for-new-comments)

Commentions supports polling for new comments. You can enable it on any component by calling the `poll` method and passing the desired interval.

```
Infolists\Components\Section::make('Comments')
    ->schema([
        CommentsEntry::make('comments')
            ->mentionables(fn (Model $record) => User::all())
            ->poll('10s')
    ]),
```

### Rendering non-Comments in the list

[](#rendering-non-comments-in-the-list)

Sometimes you might want to render non-Comments in the list of comments. For example, you might want to render when the status of a project is changed. For this, you can override the `getComments` method in your model, and return instances of the `Kirschbaum\Commentions\RenderableComment` data object.

```
use Kirschbaum\Commentions\RenderableComment;

public function getComments(?int $limit = null): Collection
{
    $statusHistory = $this->statusHistory()->get()->map(fn (StatusHistory $statusHistory) => new RenderableComment(
        id: $statusHistory->id,
        authorName: $statusHistory->user->name,
        body: sprintf('Status changed from %s to %s', $statusHistory->old_status, $statusHistory->new_status),
        createdAt: $statusHistory->created_at,
    ));

    $comments = $this->comments()->latest()->with('author')->get();

    $mergedCollection = $statusHistory->merge($comments);

    if ($limit) {
        return $mergedCollection->take($limit);
    }

    return $mergedCollection;
}
```

---

Upgrading
---------

[](#upgrading)

See [UPGRADE.md](UPGRADE.md) for upgrade instructions.

---

Security
--------

[](#security)

If you discover any security related issues, please email  instead of using the issue tracker.

Credits
-------

[](#credits)

- [Luis Dalmolin](https://github.com/luisdalmolin)
- [All contributors](https://github.com/kirschbaum-development/commentions/graphs/contributors)

Sponsorship
-----------

[](#sponsorship)

Development of this package is sponsored by Kirschbaum Development Group, a developer driven company focused on problem solving, team building, and community. Learn more [about us](https://kirschbaumdevelopment.com?utm_source=github) or [join us](https://careers.kirschbaumdevelopment.com?utm_source=github)!

License
-------

[](#license)

The MIT License (MIT). Please see [License File](LICENSE.md) for more information.

###  Health Score

54

—

FairBetter than 97% of packages

Maintenance85

Actively maintained with recent releases

Popularity53

Moderate usage in the ecosystem

Community28

Small or concentrated contributor base

Maturity41

Maturing project, gaining track record

 Bus Factor2

2 contributors hold 50%+ of commits

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 ~14 days

Total

29

Last Release

152d ago

### Community

Maintainers

![](https://www.gravatar.com/avatar/57e405b52d482c9de35b17f299d2745e8e68d9d9951aec64854f2d7fa53110bf?d=identicon)[luisdalmolin](/maintainers/luisdalmolin)

![](https://www.gravatar.com/avatar/5f56743d64d77958321d43b2df49e9696d19c9dd99995730c5c38ccae50408fa?d=identicon)[Kirschbaum](/maintainers/Kirschbaum)

---

Top Contributors

[![luisdalmolin](https://avatars.githubusercontent.com/u/403446?v=4)](https://github.com/luisdalmolin "luisdalmolin (71 commits)")[![navneetrai](https://avatars.githubusercontent.com/u/195833?v=4)](https://github.com/navneetrai "navneetrai (37 commits)")[![lisa-fehr](https://avatars.githubusercontent.com/u/6653340?v=4)](https://github.com/lisa-fehr "lisa-fehr (31 commits)")[![ItsMalikJones](https://avatars.githubusercontent.com/u/53808092?v=4)](https://github.com/ItsMalikJones "ItsMalikJones (22 commits)")[![adammparker](https://avatars.githubusercontent.com/u/5186174?v=4)](https://github.com/adammparker "adammparker (12 commits)")[![nathanheffley](https://avatars.githubusercontent.com/u/8952123?v=4)](https://github.com/nathanheffley "nathanheffley (7 commits)")[![zvizvi](https://avatars.githubusercontent.com/u/4354421?v=4)](https://github.com/zvizvi "zvizvi (3 commits)")[![agencetwogether](https://avatars.githubusercontent.com/u/53862310?v=4)](https://github.com/agencetwogether "agencetwogether (3 commits)")[![elmergustavo](https://avatars.githubusercontent.com/u/42653934?v=4)](https://github.com/elmergustavo "elmergustavo (2 commits)")[![klaare](https://avatars.githubusercontent.com/u/170330296?v=4)](https://github.com/klaare "klaare (1 commits)")[![laravel-shift](https://avatars.githubusercontent.com/u/15991828?v=4)](https://github.com/laravel-shift "laravel-shift (1 commits)")[![JoDeveloper](https://avatars.githubusercontent.com/u/18007194?v=4)](https://github.com/JoDeveloper "JoDeveloper (1 commits)")[![jayson-temporas](https://avatars.githubusercontent.com/u/29498181?v=4)](https://github.com/jayson-temporas "jayson-temporas (1 commits)")[![guetteman](https://avatars.githubusercontent.com/u/13571642?v=4)](https://github.com/guetteman "guetteman (1 commits)")[![silviugd](https://avatars.githubusercontent.com/u/26011825?v=4)](https://github.com/silviugd "silviugd (1 commits)")[![theofanisv](https://avatars.githubusercontent.com/u/6011795?v=4)](https://github.com/theofanisv "theofanisv (1 commits)")[![KamranBiglari](https://avatars.githubusercontent.com/u/102748921?v=4)](https://github.com/KamranBiglari "KamranBiglari (1 commits)")[![Copilot](https://avatars.githubusercontent.com/in/1143301?v=4)](https://github.com/Copilot "Copilot (1 commits)")

---

Tags

filamentlaravellivewire

###  Code Quality

TestsPest

Static AnalysisPHPStan

Code StyleLaravel Pint

### Embed Badge

![Health badge](/badges/kirschbaum-development-commentions/health.svg)

```
[![Health](https://phpackages.com/badges/kirschbaum-development-commentions/health.svg)](https://phpackages.com/packages/kirschbaum-development-commentions)
```

###  Alternatives

[relaticle/comments

A full-featured commenting system for Filament panels

202.9k](/packages/relaticle-comments)[simplestats-io/laravel-client

Server-side analytics for Laravel that follows the full funnel from visit to registration to payment, attributed to the channel that drove it. Revenue, MRR, churn and ad-spend profit (ROAS/CAC) per channel. GDPR compliant, ad-blocker proof.

5226.7k](/packages/simplestats-io-laravel-client)[forjedio/inertia-table

Backend-driven dynamic tables for Laravel + Inertia.js

272.0k](/packages/forjedio-inertia-table)[nomanur/filament-seo-pro

The definitive SEO toolkit for Filament — live analysis, Google preview, social cards, schema markup, and bulk management.

111.4k2](/packages/nomanur-filament-seo-pro)

PHPackages © 2026

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