byrcsc / laravel-mentions
Mention infrastructure for Eloquent models, with configurable parsing, resolution, persistence, and lifecycle events.
Fund package maintenance!
Requires
- php: ^8.3
- illuminate/contracts: ^12.0||^13.0
- illuminate/database: ^12.0||^13.0
- illuminate/events: ^12.0||^13.0
- illuminate/support: ^12.0||^13.0
- spatie/laravel-package-tools: ^1.16
Requires (Dev)
- larastan/larastan: ^3.3.1
- laravel/pint: ^1.14
- nunomaduro/collision: ^8.8
- orchestra/testbench: ^10.0||^11.0
- pestphp/pest: ^4.0
- pestphp/pest-plugin-arch: ^4.0
- pestphp/pest-plugin-laravel: ^4.0
- phpstan/extension-installer: ^1.4
- phpstan/phpstan-deprecation-rules: ^2.0
- phpstan/phpstan-phpunit: ^2.0
This package is auto-updated.
Last update: 2026-08-11 09:10:40 UTC
README
Laravel Mentions adds @mentions to Eloquent models. It detects mentions in plain text or editor markup, resolves them to models, and stores queryable records. When the text changes, it syncs those records and fires an event for each mention added or removed.
Everything else stays yours. The package sends no notifications, renders no HTML, and ships no routes, controllers, or JavaScript.
Read the versioned documentation for the full installation, configuration, and usage guides.
| Laravel | Tested PHP versions |
|---|---|
| 12.x | 8.3, 8.4 |
| 13.x | 8.3, 8.4 |
Installation
Install the package:
composer require byrcsc/laravel-mentions
Publish and run the migration:
php artisan vendor:publish --tag="mentions-migrations"
php artisan migrate
Publish the config file to define which models handles resolve to:
php artisan vendor:publish --tag="mentions-config"
How it works
Each mention record links the source model containing the text to the target model being mentioned. Both sides are polymorphic, so comments can mention users, tasks can mention teams, and your own models can mention anything you configure.
Because mentions are stored instead of parsed on demand, you can query them in either direction. Each record also snapshots the matched handle, so history stays readable after a handle changes.
The package includes two parsers:
- The regex parser detects handles such as
@janein plain text. - The markup parser detects
data-mention-idattributes emitted by rich text editors such as Tiptap and Trix.
You can choose a parser per model, replace either parser, and provide custom resolvers for tenant scoping or other lookup rules.
Quick start
Add HasMentions to a model containing mentionable text:
use Byrcsc\Mentions\Concerns\HasMentions; use Illuminate\Database\Eloquent\Model; class Comment extends Model { use HasMentions; /** @var list<string> */ protected array $mentionableAttributes = ['body']; }
Add Mentionable to a model that can be mentioned:
use Byrcsc\Mentions\Concerns\Mentionable; class User extends Authenticatable { use Mentionable; }
Point the default resolver at that model and its handle column:
// config/mentions.php 'resolvers' => [ 'users' => [ 'model' => App\Models\User::class, 'column' => 'name', ], ],
This uses name so it works with Laravel's default User model. In a real
application, prefer a dedicated, uniquely indexed username column.
Mentions now sync whenever the source model is saved:
$comment = Comment::create([ 'body' => 'Thanks @jane, can you take a look?', ]); $comment->mentioned(); // Mentioned models $comment->mentions(); // Underlying mention records $jane->mentionedIn(); // Records that mention Jane
Syncing and events
Saving a model with HasMentions creates new mentions and removes stale ones.
Call $model->syncMentions() when you need to sync explicitly, including after
saveQuietly(), query-builder updates, or bulk imports that bypass Eloquent
events.
Listen for MentionCreated and MentionRemoved to send notifications or run
other application logic:
use Byrcsc\Mentions\Events\MentionCreated; Event::listen(function (MentionCreated $event) { // $event->mention is the new mention record. });
Deleting a source prunes its mention records without firing removal events.
Soft deleting keeps them. MentionRemoved means the text stopped mentioning a
target, not that a source record was cleaned up.
Querying mentions
Find source models that mention a target:
$comments = Comment::whereMentions($jane)->get();
Query the underlying records from either side:
$comment->mentions()->with('target')->get(); $jane->mentionedIn()->with('source')->get();
Out of scope
The package deliberately leaves these concerns to your application:
- Sending notifications
- HTTP endpoints and autocomplete
- JavaScript and editor integration
- Rendering mentions as links or HTML
- Permission checks
Versioning
The package follows semantic versioning.
- Upgrading within
1.xis safe. Nothing you use will break. - Only a new major version, like
2.0.0, can break your code. - If the README or the documentation describes it, it is safe to build on. If they don't, treat it as internal and expect it to change.
Bug fixes go into the newest version only. To get a fix, upgrade to it.
Questions and issues
- Stuck, or have an idea? Start a discussion. Usage questions and feature ideas both live there.
- Found a bug you can reproduce? Open an issue. A failing test is the fastest way to a fix, and a short reproduction is the next best thing.
- Found a security problem? Please don't open a public issue. See SECURITY.md for how to report it privately.
- Planning a pull request? CONTRIBUTING.md covers the setup and the three checks it needs to pass.
This package is maintained by one person, so replies can take a while. Everything gets read.
License
MIT. See LICENSE.md. Changelog in CHANGELOG.md.