NewWe open-sourced 50+ Laravel packages
Custom AI apps, agents and automation — Roundly ConsultingRoundly
All packages

Open source

Likes for Laravel

Install
composer require roundly-consulting/likes-for-laravel
Requires: PHP ^8.4 · Laravel ^12.0|^13.0

Overview

Native likes and reactions for Laravel. Any Eloquent model can give likes, any model can receive them, and a single polymorphic likes table records who liked what — with idempotent verbs, optional typed reactions, popularity and trending ranking, single-query feed hydration and events your app can listen to. MIT-licensed and built only on Laravel’s own components plus the Roundly package toolkit — no third-party dependencies.

What you get

Any actor, any likeable

Users, teams or any Eloquent model can give likes to any other model — one polymorphic likes table records who liked what.

Idempotent verbs

like(), unlike() and toggleLike() return the is-liked-now state; repeats are no-ops and a re-like restores the old row.

Typed reactions

Opt into love, wow or your own set via an allowlist, and switch a reaction in place with a clean ReactionChanged event.

Feeds without N+1

withLikedState() and withLikesCount() hydrate the viewer’s state and counts for a whole page in a single query.

Weighted & trending ranking

Rank by a weighted reaction score or recency-boosted trending activity — portable SQL for SQLite, MySQL and PostgreSQL.

Events & opt-in broadcasting

Liked, Unliked and ReactionChanged fire only on real changes and can broadcast over Laravel Echo when you turn it on.

Testing toolkit

A recording Likes::fake(), acting-actor helpers, Pest matchers and a model factory for your own test suite.

Documentation

Installation

Install via Composer, then publish and run the likes migration — publish the config first for UUID or ULID keys or a custom table name.

Configuration

Every config key and its default — model, table, key type, reactions, actor resolver, weights, trending and broadcasting.

Database schema & key types

The single polymorphic likes table, soft deletes, UUID/ULID key types and swapping in your own Like model.

Models & traits

Add HasLikes to models that can be liked and GivesLikes to actors; the relations, the Likeable contract and the Like model.

The Likes facade

One-line likes as the signed-in user, the actor()/as() builder, the Likes::for() read handle and custom actor resolution.

DI and actions

Skip the facade: inject LikeManager or call a single-purpose action with a LikeData DTO — the facade method → action map.

Liking, unliking & toggling

Idempotent like, unlike and toggle through the Likes facade or the model trait, returning the is-liked-now state, plus bulk likeMany().

Checking state & counting

Check whether an actor liked a model and count likes with Likes::has() and Likes::for() — live or from an eager-loaded count.

Query scopes

Order by like count, filter to what an actor liked or didn’t, and hydrate likes_count — all composable, all typed.

Feed hydration (no N+1)

withLikedState() adds is_liked and liked_reaction for the viewer to a whole feed page in one query — guest-safe.

Weighted score & trending

Rank by a weighted reaction score or recency-boosted trending activity, with portable SQL across SQLite, MySQL and PostgreSQL.

Typed reactions

Turn plain likes into typed reactions — love, wow, laugh or your own set — guarded by a config allowlist.

Switching reactions

react() keeps one active reaction per actor and item, switching it in place and firing only ReactionChanged.

Reaction breakdown

Likes::for()->summary() returns totals, per-type counts, the top reaction and the viewer’s own reaction for reaction bars.

What an actor liked

likedItems() and likesOf() return a real MorphToMany of the models an actor likes — eager-loadable and paginatable.

Blade directive

The @liked conditional renders the right heart state for the current or an explicit actor and reaction type.

JSON API output

LikeResource and toLikeArray() return the like count, the viewer’s state and the per-reaction breakdown as JSON.

Events

Liked, Unliked and ReactionChanged fire only on real changes, one event per change — plus an optional persisted counter column.

Broadcasting

Opt-in broadcasting of Liked, Unliked and ReactionChanged over Laravel Echo on likes.{morph}.{id} channels.

Exceptions

InvalidReactionTypeException, NoAuthenticatedActorException and their shared LikesException base.

Testing

Likes::fake() records every like, unlike and reaction while still writing rows — plus acting-actor helpers, Pest matchers and a Like factory.

Requirements

PHP 8.4+, Laravel 12 or 13, and the Roundly package toolkit — no PHP extensions or third-party packages.

Show your open-source love

This package is free and MIT-licensed. If it saves you time, a one-off donation or a Patreon membership keeps it maintained, tested and documented.

More ways to support, including crypto

By donating, you agree to our donation terms.

Want this built into your product?

We integrate our packages into custom Laravel and AI builds. Tell us what you're working on and we'll reply within 48 hours.