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

Xetaravel Mentions Laravel Package

xetaio/xetaravel-mentions

A Laravel package for parsing and rendering @mentions in text, converting them into links and optionally notifying mentioned users. Includes a user trait, configurable mention syntax, events, and Blade helpers for easy integration.

View on GitHub
Deep Wiki
Context7

Getting Started

  • Install with composer require xetaio/xetaravel-mentions. As of 12.0.0 the package targets Laravel 12; the major version bump tracks the framework floor rather than an API break, so ^12.0 is the constraint to use on a Laravel 12 app (stay on 11.x for Laravel 11).
  • Publish and run the package assets: publish the config (config/mentions.php) and the migrations, then php artisan migrate. The migration creates the polymorphic mentions table that stores the parsed @handle → model mapping.
  • Wire up the two traits:
    • HasMentions on the model that owns the text (e.g. Post, Comment).
    • Mentionable on the model that can be mentioned (e.g. User).
  • Point the config pool at your mentionable model (App\Models\User::class). This is the class the parser resolves handles against — if it's wrong, parsing silently yields zero mentions.
  • First use case: a comment body containing @johndoe is saved, the package parses the field, resolves johndoe against the pool, inserts rows into mentions, and the configured notifier class fires per mentioned model. Start here — save a comment, assert a row in mentions, then assert the notification — before touching rendering or feeds.

Where to look first: config/mentions.php (regex, pool, notifier, parser template), then the mentions table schema, then the trait methods on HasMentions.

Implementation Patterns

  • Parse on write, index in the DB. Treat mentions as a derived index of the raw text, not the source of truth. Call the trait's sync/parse method in a saved model event or explicitly in your form request/action so every write path (API, Nova, console seeder) stays consistent.
  • Sync, don't append. On update, use the sync-style call so removed @handles drop their rows. Appending on each save is the classic bug that leaves stale mentions and produces phantom notifications.
  • Diff before notifying. Compute added vs. removed mentions on update and only notify the additions; otherwise every edit re-notifies everyone already mentioned.
  • Rendering. Use the config parser template (a link pattern with the handle/URL) to turn raw text into HTML at render time. Keep the raw text in the column and linkify on output — do not store pre-linked HTML, or handle renames break old content.
  • Feeds. $user->mentions (morphMany, from Mentionable) is your "mentions of me" source. Eager load the mentioner (with('mentioner')) so an activity feed doesn't N+1, and paginate on the mentions query rather than on the parent models.
  • Multi-type pools. Extending the pool beyond User (e.g. Team) means handles must be unambiguous, or you need a prefixed syntax. Model the morph type in the config/parser and resolve by type.
  • Notifications. Point notifier at a queued notification class, exclude the author from recipients ($post->user_id), and let a Notification::fake() test cover the "author mentions self" case.
  • API layer. Return the raw body plus a resolved list of mention DTOs (id, name, url) from your resource, so clients can render mentions without re-implementing the regex.

Gotchas and Tips

  • 12.0.0 is a compatibility release. The only change is Laravel 12 support. Upgrade path is a composer constraint bump plus a test run; there's no new API to adopt, but the major number means don't mix ^11 and ^12 across a monorepo.
  • Regex is config, and it is load-bearing. The handle pattern in mentions.php defines what counts as a mention. Changing it does not retroactively re-parse existing rows — write a one-off backfill job that re-syncs every owner model after any regex change.
  • False positives. Naive @handle regexes match email addresses ([email protected]) and mentions inside code fences. Tighten the pattern and/or strip code blocks before parsing if your text allows them.
  • Handle charset and case. Decide case sensitivity up front; if handles are case-insensitive in the pool lookup but stored case-sensitively, you'll get duplicate/missed mentions. Unicode usernames need the u flag and a compatible pattern.
  • Silent no-ops. A mention of a non-existent handle, or a pool class that doesn't implement Mentionable, just doesn't create a row — no exception. Log or assert in tests when you expect a resolution.
  • XSS. Always e() the raw body before injecting the parser's anchor HTML, or build the link around an escaped fragment. Never {!! $post->body !!} with a linkified string containing unescaped user input.
  • Cleanup. Add FK/cascade or a deleted hook so deleting a post/comment removes its mentions rows; the polymorphic relation won't cascade for you on all drivers.
  • Debugging. When mentions don't appear, check in order: config pool, regex match against the literal text, the notifier binding in the container, and finally whether the sync method is actually called on that write path.
  • Extension points. The parser template and the notifier class are the intended seams — prefer swapping those over forking the package. If you need custom resolution (e.g. soft-deleted users), wrap the pool lookup in your own service rather than patching the trait.
  • Testing. Use Notification::fake() and a factory that creates mentions via the trait, so tests exercise the same parse path as production instead of inserting rows manually.
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.
mehedimi/laravel-amp-mail
happones/laravel-vue-i18n-generator
jwerd/inertia-table
siberfx/flysystem-wasabi
hollyit/token-replace
ippanelcom/laravel-sdk
adachsoft/changelog-linter
adachsoft/collection
payerurl/telegrambot-crypto-payment-instant-payout
dskripchenko/laravel-hybrid-search
riorizkyrainey/lara-ced
mehedimi/static-vel
zharp/zharp
nonsapiens/bigquery-model-sync
lgu-bayambang-ict-office/lgu-laravel-development-standards
andydefer/laravel-support
se7enxweb/flysystem
lampwick/laravel
jeslage/statamic-emojis
micahdshackelford/rmap-laravel