byrcsc/laravel-mentions

Mention infrastructure for Eloquent models, with configurable parsing, resolution, persistence, and lifecycle events.

Maintainers

Package info

github.com/byrcsc/laravel-mentions

Forum

Documentation

pkg:composer/byrcsc/laravel-mentions

Transparency log

Fund package maintenance!

Buy Me A Coffee

Statistics

Installs: 0

Dependents: 0

Suggesters: 0

Stars: 0

Open Issues: 0

v1.0.0 2026-08-11 09:08 UTC

This package is auto-updated.

Last update: 2026-08-11 09:10:40 UTC


README

Latest Version on Packagist GitHub Tests Action Status GitHub PHPStan Action Status Total Downloads

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 @jane in plain text.
  • The markup parser detects data-mention-id attributes 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.x is 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.