End-to-end Mentions in Laravel 5 & 6
, (*1)
Abandoned
Unfortunately, I don't have the time to adequately maintain this package. I recommend Xetaravel-Mentions which appears to be better maintained with similar functionality., (*2)
In hindsight, this package has tried to do too much to implement this functionality. If you're looking to implement mentions, I think you'd be better off implementing the front-end manually, and abstracting the back-end to that package above or writing your own API., (*3)
Hope this helps!, (*4)
This Laravel >=5.4 package provides an easy way to setup mentions for Eloquent models. It provides the front-end for inserting mentions into content-editable elements, the back-end for associating mentions with models and lastly an elegant way to notify the mentioned models that they have been mentioned., (*5)
Here are a few short examples of what you can do:, (*6)
// Mention a single user
$comment->mention($user);
// Mention a collection of users
$comment->mention($users);
// Handle the form data
$comment->mention($request->mentions);
// Get all mentions, resolved to their models
$comment->mentions();
// Unmention a single user
$comment->unmention($user);
// Unmention a collection of users
$comment->unmention($users);
It handles notifications for you as well. If your mentions config has auto_notify enabled, it will do it for you. If you need to handle the logic yourself, disable auto_notify and explicitly notify the mention, for example:, (*7)
$mention = $comment->mention($user);
$mention->notify();
Requirements
Installation
You can install this package via composer using this command:, (*8)
composer require jameslkingsley/laravel-mentions
If you're using Laravel 5.5 or greater this package will be auto-discovered, however if you're using anything lower than 5.5 you will need to register it the old way:, (*9)
Next, you must install the service provider in config/app.php:, (*10)
'providers' => [
...
Kingsley\Mentions\MentionServiceProvider::class,
];
Now publish the migration, front-end assets and config:, (*11)
php artisan vendor:publish --provider="Kingsley\Mentions\MentionServiceProvider"
After the migration has been published you can create the mentions table by running the migrations:, (*12)
php artisan migrate
This is the contents of the published config file:, (*13)
return [
// The middleware that should be applied to all
// routes that are registered in this package.
'middleware' => null,
// Pools are what you reference on the front-end
// They contain the model that will be mentioned
'pools' => [
'users' => [
// Model that will be mentioned
'model' => 'App\User',
// Filter class that alters the query
'filter' => null,
// The column that will be used to search the model
'column' => 'name',
// Notification class to use when this model is mentioned
'notification' => 'App\Notifications\UserMentioned',
// Automatically notify upon mentions
'auto_notify' => true
]
]
];
Usage
First you will need to import Tribute., (*14)
npm install tributejs --save-dev
Then include Tribute in your bootstrap.js file and assign it globally., (*15)
import Tribute from "tributejs";
window.Tribute = Tribute;
Now in your bootstrap.js file you can import the Mentions class and also assign it globally., (*16)
import Mentions from "./laravel-mentions";
window.Mentions = Mentions;
Now to include the styling just import it into your SCSS file., (*17)
@import "laravel-mentions";
Now let's setup the form where we'll write a comment that has mentions:, (*18)
Next add the script to initialize the mentions:, (*19)
new Mentions({
// Additional headers to send
// to possibly authenicate
// the current user
http: {
headers: [
// {
// name: "Authorization",
// value: "Bearer your-user-api-token"
// }
]
},
// Input element selector
// Defaults to .has-mentions
input: ".has-mentions",
// Output form field selector
// Defaults to #mentions
output: "#mentions",
// Pools
pools: [
{
// Trigger the popup on the @ symbol
// Defaults to @
trigger: "@",
// Pool name from the mentions config
pool: "users",
// Same value as the pool's 'column' value
display: "name",
// The model's primary key field name
reference: "id"
}
]
});
Now onto the back-end. Choose the model that you want to assign mentions to. In this example I'll choose Comments. We'll import the trait and use it in the class., (*20)
namespace App;
use Illuminate\Database\Eloquent\Model;
use Kingsley\Mentions\Traits\HasMentions;
class Comment extends Model
{
use HasMentions;
}
Next switch to the controller for where you store the comment. In this case it's CommentController. Create the comment however you like, and afterwards just call the mention method., (*21)
public function store(Request $request)
{
// Handle the comment creation however you like
$comment = Comment::create($request->all());
// Call the mention method with the form mentions data
$comment->mention($request->mentions);
}
That's it! Now when displaying your comments you can style the .mention-node class that is inserted via Tribute. That same node also has a data-object attribute that contains the pool name and reference value, eg: users:1., (*22)
Editing Content With Mentions
You'll most likely need to edit the text content, so it's necessary to restore the mentions list in the form.
It's as simple as this:, (*23)
<input
type="hidden"
name="mentions"
id="mentions"
value="{{ $comment->mentions()->encoded() }}"
/>
Then on the back-end you can update the model's mentions by doing the following:, (*24)
$comment
->clearMentions()
->mention($request->mentions);
Notifications
If you want to use notifications, here's some stuff you may need to know., (*25)
- When a mention is notified, it will use Laravel's built-in Notification trait to make the notification. That means the model class defined in the pool's config must have the
Notifiable trait.
- It will use the notification class defined in the pool's config, so you can handle it differently for each one.
- The data stored in the notification will always be the model that did the mention, for example
$comment->mention($user) will store $comment in the data field.
- __construct method of notification class gets the model that did the mention as an argument, for example
$comment->mention($user) will get $comment on the constructor.
Filters
You might want to apply some custom filters to the model when it retrieves the records. To do this just create a class somewhere in your app, then add it to the mention config:, (*26)
return [
'pools' => [
'users' => [
...
'filter' => 'App\Filters\UserFilter',
...
]
]
];
This is what your filter class should look like. It just has one static method called handle that takes the query as an argument, and must return the query., (*27)
<?php
namespace App\Filters;
class UserFilter
{
/**
* Handles the filtering and returns the updated query.
*
* @return Illuminate\Database\Eloquent\Builder
*/
public static function handle($query)
{
// Apply your filters here!
return $query->where('someColumn', 'someValue');
}
}
Resources
If you'd like to change the JSON response that the /api/mentions route returns, you can create your own resource class. To begin with head over to the Laravel docs to create and setup a resource class., (*28)
Once you have your resource class, simply add it to your mention config in one or more of your pools, such as:, (*29)
return [
'pools' => [
'users' => [
...
'resource' => 'App\Resources\UserCollection',
...
]
]
];
Middleware
If you'd like you can optionally add middleware to the /api/mentions route. This can be useful in case you want to protect the route behind an authentication guard. Head over to the Laravel docs find out more about middleware., (*30)
return [
'middleware' => [
'your-middleware-here',
],
//
];