Installation:
composer require devdojo/laravel-reactions
Add the service provider to config/app.php:
DevDojo\LaravelReactions\Providers\ReactionsServiceProvider::class,
Publish and run migrations:
php artisan vendor:publish --provider="DevDojo\LaravelReactions\Providers\ReactionsServiceProvider" --tag="migrations"
php artisan migrate
First Use Case:
Add the Reacts trait to your Eloquent model (e.g., Post):
use DevDojo\LaravelReactions\Traits\Reacts;
class Post extends Model
{
use Reacts;
}
Now, a reactions() relationship is automatically added to your model.
Adding Reactions:
// User reacts to a Post with a specific emoji (e.g., 'like')
$post->reactions()->attach($user->id, ['emoji' => 'like']);
Fetching Reactions:
// Get all reactions for a Post
$reactions = $post->reactions;
// Get reactions by emoji (e.g., 'like')
$likes = $post->reactions->where('emoji', 'like');
Counting Reactions:
// Total reactions
$totalReactions = $post->reactions()->count();
// Count reactions by emoji
$likeCount = $post->reactions()->where('emoji', 'like')->count();
Polymorphic Reactions:
Add the Reactable trait to any model to enable reactions on it:
use DevDojo\LaravelReactions\Traits\Reactable;
class Comment extends Model
{
use Reactable;
}
Now, reactions can be attached to both Post and Comment:
$comment->reactions()->attach($user->id, ['emoji' => 'love']);
Customizing Reactions:
Extend the Reaction model to add custom fields:
class CustomReaction extends \DevDojo\LaravelReactions\Models\Reaction
{
protected $casts = [
'metadata' => 'array',
];
}
Update the Reacts trait to use your custom model:
use DevDojo\LaravelReactions\Traits\Reacts as BaseReacts;
trait Reacts
{
use BaseReacts;
protected static function getReactionModel()
{
return \App\Models\CustomReaction::class;
}
}
API Endpoints: Create routes for adding/removing reactions:
Route::post('/posts/{post}/react', [PostReactionController::class, 'store']);
Route::delete('/posts/{post}/react', [PostReactionController::class, 'destroy']);
Frontend Integration: Use JavaScript to toggle reactions dynamically:
// Example: Toggle a 'like' reaction
async function toggleReaction(postId, emoji) {
const response = await fetch(`/posts/${postId}/react`, {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify({ emoji })
});
return response.json();
}
Real-Time Updates: Use Laravel Echo/Pusher to update reaction counts in real-time:
// Broadcast reaction changes
$post->reactions()->attach($user->id, ['emoji' => 'like']);
broadcast(new ReactionUpdated($post, 'like'));
Validation: Validate reactions in a Form Request:
public function rules()
{
return [
'emoji' => 'required|in:like,love,laugh,care,sad,angry,wow',
];
}
Migration Conflicts:
If you manually modify the reactions or reactables tables, ensure you update the package's migrations or disable them in config/reactions.php:
'migrations' => [
'run' => false,
],
Polymorphic Relationships:
The reactables table uses reactable_type and reactable_id for polymorphic relationships. Ensure these columns are correctly populated when attaching reactions to models.
Duplicate Reactions: By default, the package does not prevent duplicate reactions (e.g., a user reacting twice with the same emoji). Add validation in your controller or use a unique constraint:
$post->reactions()->updateOrCreate(
['user_id' => $user->id, 'emoji' => 'like'],
['emoji' => 'like']
);
Performance:
Avoid eager-loading reactions for models with many reactions. Use withCount for counts:
$posts = Post::withCount(['reactions' => function($query) {
$query->where('emoji', 'like');
}])->get();
Check Database:
Verify the reactions and reactables tables contain expected data:
php artisan tinker
>>> \DevDojo\LaravelReactions\Models\Reaction::all();
>>> \DevDojo\LaravelReactions\Models\Reactable::all();
Log Queries: Enable Laravel query logging to debug relationship issues:
DB::enableQueryLog();
$post->reactions; // Trigger query
dd(DB::getQueryLog());
Clear Cached Compiled Views: If reactions aren’t displaying, clear the view cache:
php artisan view:clear
Custom Reaction Models:
Override the Reaction model to add fields like created_at timestamps or metadata:
class Reaction extends \DevDojo\LaravelReactions\Models\Reaction
{
protected $fillable = ['user_id', 'emoji', 'metadata'];
}
Event Listeners: Listen for reaction events to trigger actions (e.g., notifications):
// In EventServiceProvider
protected $listen = [
\DevDojo\LaravelReactions\Events\ReactionAdded::class => [
\App\Listeners\SendReactionNotification::class,
],
];
Scopes:
Add custom scopes to the Reaction model for querying:
public function scopeRecent($query, $minutes = 5)
{
return $query->where('created_at', '>=', now()->subMinutes($minutes));
}
Middleware:
Protect reaction endpoints with middleware (e.g., auth):
Route::post('/posts/{post}/react', [PostReactionController::class, 'store'])->middleware('auth');
Table Names:
Customize table names in config/reactions.php:
'tables' => [
'reactions' => 'custom_reactions',
'reactables' => 'custom_reactables',
],
Default Emojis: Override default emojis in the config:
'emojis' => ['heart', 'star', 'thumbs-up'],
Soft Deletes:
Enable soft deletes for reactions by adding SoftDeletes to the Reaction model and configuring the trait:
use Illuminate\Database\Eloquent\SoftDeletes;
class Reaction extends \DevDojo\LaravelReactions\Models\Reaction
{
use SoftDeletes;
}
How can I help you explore Laravel packages today?