Weave Code
Weaver
Helps Laravel developers discover, compare, and choose open-source packages. See popularity, security, maintainers, and scores at a glance to make better decisions.
Feedback
Share your thoughts, report bugs, or suggest improvements.
Subject
Message

Activity Comments Laravel Package

liberusoftware/activity-comments

Add threaded comments to any Laravel activity log record. This package provides a lightweight comment model, migrations, and relationships so you can attach, nest, and retrieve discussions on logged events with minimal setup.

View on GitHub
Deep Wiki
Context7

Getting Started

This is a low-adoption package (0 stars, 0 dependents), so treat the README and src/ as the source of truth rather than assuming Laravel-ecosystem conventions. The names below are illustrative; confirm namespaces, config keys, and method signatures against the repo before shipping.

Minimal setup

composer require liberusoftware/activity-comments

php artisan vendor:publish --provider="Liberu\ActivityComments\ActivityCommentsServiceProvider"
php artisan migrate

Then add the package trait to the models that author or receive activity:

use Liberu\ActivityComments\Traits\HasActivityComments;

class Post extends Model
{
    use HasActivityComments;
}

class User extends Authenticatable
{
    use HasActivityComments; // or the author/mentionable trait
}

Where to look first

  1. README.md — install order, required traits, published config.
  2. config/activity-comments.php — model bindings, morph aliases, mention/notification drivers, visibility defaults.
  3. database/migrations/ — table names and polymorphic columns; run these before writing queries.
  4. src/Contracts/ — interfaces you can rebind (mention parser, visibility resolver, subscription manager).
  5. src/Traits/ — which trait belongs on the author vs. the commentable model.
  6. routes/ and src/Http/ — whether the package ships controllers/routes or expects you to wire your own.

First use case

Attach a comment to a Post and render a timeline:

$post->comment(auth()->user(), 'Looks good — cc @jane');
$post->comments()->latest()->paginate(20);

If those methods don't exist verbatim, look for a service or action class (e.g. CommentService, ActivityManager) — this package family typically favors actions over model magic.


Implementation Patterns

Commentable + author separation

Keep two concerns distinct: the model that owns a timeline (Post, Ticket, Project) and the model that acts (User). Apply the commentable trait to the former and the author/mentionable trait to the latter. Mixing them causes ambiguous morph targets.

Morph map early

Register stable aliases before the first insert. Changing them later orphans polymorphic rows:

// AppServiceProvider::boot()
Relation::morphMap([
    'post'    => \App\Models\Post::class,
    'user'    => \App\Models\User::class,
    'ticket'  => \App\Models\Ticket::class,
]);

Timeline queries

Treat timelines as read models. Scope by visibility, eager-load author and attachments, and paginate at the query level:

$timeline = $post->activityFeed()
    ->with(['author', 'attachments', 'mentions.user'])
    ->visibleTo(auth()->user())
    ->latest()
    ->cursorPaginate(25);

If visibleTo isn't provided, implement it as a local scope that delegates to the package's visibility contract.

Mentions

Parse on write, resolve on read. Store mention rows (user_id + comment_id) rather than re-parsing text on every render — it makes notification fan-out and permission checks tractable. If the package exposes a parser contract, bind your own for handles like @jane vs @jane@instance.

Subscriptions

Subscribe the author and all mentioned users on creation; unsubscribe on explicit user action only. Avoid subscribing on every edit — it produces duplicate rows and surprise notifications. De-duplicate with a unique index on (user_id, subscribable_type, subscribable_id).

Attachments

Decide early whether attachments use the package's storage abstraction or Laravel's filesystem/Media Library. If it's configurable, pin the disk in config ('disk' => 's3') rather than relying on the default. Store metadata (size, mime, original name) alongside the path.

Authorization

Wire policies per commentable model, and let the package's gate checks call them. Do not rely on middleware alone — comment visibility often needs to be enforced inside the query for list endpoints:

Gate::define('comment-on', fn (User $u, Post $p) => $u->can('update', $p));

Notifications

Push mention and reply notifications onto a queue. Synchronous fan-out on a comment with 50 mentions will block the request. Use an event listener on the package's comment-created event rather than overriding the service.

API surface

Expose comments as resources with stable shapes, and keep visibility filtering server-side. Returning a visibility field to the client is fine; trusting a client-supplied one is not.


Gotchas and Tips

  • Zero-adoption risk. With 0 stars and 0 dependents, pin an exact version in composer.json and read the diff before upgrading. The last release date (2026-10-27) is a future-dated signal — verify the tag actually exists and matches composer.lock.
  • Trait collisions. Both the package trait and your own HasComments/HasMentions traits may define comments(), mentions(), or subscribe(). Resolve with insteadof or rename in your wrapper.
  • Migration ordering. Polymorphic tables must exist before you backfill. Run package migrations before any app migration that seeds comments.
  • Config caching. After changing config keys, run php artisan config:clear. Package configs read at boot won't reflect edits otherwise.
  • Visibility leakage. The most common bug in timeline packages: ->visibleTo() applied to the paginated query but not to counts, exports, or search endpoints. Centralize it in a repository or scope.
  • Mention parsing edge cases. Handles inside code blocks, email addresses ([email protected]), and trailing punctuation will all produce false positives. Unit-test the parser with a fixture set.
  • Duplicate subscriptions. Add a DB unique constraint, not just an application-level check — concurrent writes will race.
  • N+1 on timelines. Eager-load author, mentions.user, and attachments by default in a base query scope; a 25-item page without eager loading can easily become 100+ queries.
  • Soft deletes. Decide whether deleted comments remain in threads (tombstoned) or vanish. If tombstoned, ensure counts and pagination account for them consistently.
  • Attachment orphans. Deleting a comment rarely deletes its files. Add an observer or scheduled cleanup.
  • Event coverage. Check whether the package dispatches CommentCreated, Mentioned, Subscribed. If it doesn't, wrap creation in your own action class so you have a hook.
  • Debugging. DB::listen() around a single comment creation is the fastest way to see what the package actually writes. php artisan tinker against the trait methods beats guessing from the README.
  • Extension points. The contracts directory is where you get leverage: rebind the mention parser, visibility resolver, or notification dispatcher in a service provider rather than forking. If those contracts don't exist, that's a signal the package is thin and you'll own most of the behavior anyway.
  • Fallback plan. Given the adoption profile, budget for the possibility that you outgrow the package. Keep your usage behind an app-level CommentService so swapping implementations later is a one-file change.
Weaver

How can I help you explore Laravel packages today?

Conversation history is not saved when not logged in.
Prompt
Add packages to context
No packages found.
skyraptor/chatter
edlugz/sasapay
abbasudo/artisan-route
mirvan/ippanel
ignibyte/aic-framework
glavweb/data-schema-bundle
glavweb/datagrid-bundle
tacticmedia/scim-server
uni-method/frame
neika-ai/sdk
adachsoft/php-code-style
pharaonic/laravel-notification-dependencies
beautinow/translug
dev-brainiac/bot-cloaked
octoberrain/html
octoberrain/extension
octoberrain/exception
octoberrain/contracts
adachsoft/api-version-bundle
cgv/localized-resource