Weave Code
Weaver
Helps Laravel developers discover, compare, and choose open-source packages. See popularity, security, maintainers, and scores at a glance to make better decisions.
Feedback
Share your thoughts, report bugs, or suggest improvements.
Subject
Message

Laravel Likeable Laravel Package

turahe/laravel-likeable

Laravel Likeable adds likes and dislikes to any Eloquent model in minutes. Prepare your model, then use built-in methods, scopes, events, and console commands to manage reactions with clean, tested Laravel integration.

View on GitHub
Deep Wiki
Context7

Technical Evaluation

Architecture fit. The package is idiomatic modern Laravel: a service provider, a Likeable contract plus trait mixin, most logic pushed into a LikeableService, Eloquent models for Like and LikeCounter, and container bindings so Contracts\Like, Contracts\LikeCounter, and Contracts\LikeableService can be swapped for first-party implementations. That is the right shape for a reusable domain component — it means our application code can depend on the package's contracts rather than its concrete models, and it gives us a documented extension seam if we later need custom reaction types or counter behaviour. Storage is polymorphic (likeable_type/likeable_id), so one pair of tables serves every likeable model, and a denormalised counter table keeps likesCount reads cheap. Likes and dislikes are mutually exclusive by design — a deliberate product semantic, not an implementation detail.

Integration feasibility. High. composer require, publish migrations, migrate, then implements Likeable + use Likeable on each model. A competent Laravel developer reaches a working vertical slice in under a day. There is no front-end opinion, no view publishing, no config file sprawl — it fits API-first, Inertia, and Livewire stacks identically. The published migration means the schema lives in our repository, which is the single most important fact for exit risk: our data outlives the package.

Technical risk. The dominant risk is vendor risk, not technical risk. Nine stars and zero dependents means effectively no peer review, no community bug-finding, and no observable "who else runs this in production." The project's engineering hygiene is unusually good for that level of adoption — 79 tests, PHP 8.3/8.4/8.5 × Laravel 10–13 CI matrix, Larastan, Pint, Codecov, conventional commits, automated changelog and semver releases — but hygiene is not the same as production hardening under load. Two further flags: (1) the package is PHP 8.3+, which excludes Laravel 10 applications still on PHP 8.1/8.2 and may force a runtime upgrade first; (2) the API surface (LikeableService, LikeCounter, collectLikers, likesDiffDislikesCount, likeable:recount) mirrors cybercog/laravel-love closely, which suggests a fork or reimplementation of an abandoned predecessor. Confirm provenance and the license chain before adopting — if it is a revived fork, that is actually a positive (mature API, fresh maintenance) but it should be a conscious decision, not an accident. Secondary risks: counter drift between the likes table and the counter table, event listeners firing in-process and potentially aborting a like, and counter-row contention under viral load.

Key questions.

  • Do the shipped migrations create a unique index on (likeable_type, likeable_id, user_id, type) and FKs with explicit cascade behaviour on liker/user deletion? Or will double-submits and orphaned likes be our problem?
  • Are like/unlike and the counter update wrapped in a single DB transaction, and how is the counter row locked? Atomic increment or read-modify-write?
  • Are ModelWasLiked/ModelWasUnliked/ModelWasDisliked/ModelWasUndisliked dispatched after commit, and are listeners expected to be queued? What happens to the like if a listener throws?
  • Is likeable:recount chunked and memory-bounded — safe to run against a production table while traffic is live?
  • Is Laravel 13 support validated against a released framework version or a dev branch?
  • Who has commit rights and what is the security-issue response expectation? Is there a security policy with a real SLA or just a boilerplate section?
  • How do likesCount accessors behave when not eager-loaded — can we guarantee no N+1 in listing endpoints?

Integration Approach

Stack fit. Backend-only Eloquent concern; compatible with any Laravel 10–13 app on PHP 8.3+, MySQL/Postgres (SQLite is viable for tests but its coarse write locking makes counter contention behaviour non-representative — do not performance-test on SQLite). The likeable:recount command accepts morph-map aliases, so it composes with Relation::enforceMorphMap(), which we should be using anyway.

Migration path. (1) Spike on a throwaway branch against a copy of production schema. (2) Publish migrations with vendor:publish --provider="Turahe\Likeable\LikeableServiceProvider" --tag=migrations and amend them in our repo before running — add the unique index, add FKs with cascadeOnDelete or nullOnDelete per policy, and confirm index coverage for the whereLikedBy / orderByLikesCount scopes. Published migrations are ours forever; treat the vendor version as a starting draft. (3) Register morph aliases. (4) Apply the trait to exactly one low-stakes model first.

Compatibility. Gate on three constraints in CI: PHP >=8.3, Laravel range, and DB driver. Because the package releases frequently via automated version bumps, pin an exact version in composer.json and treat upgrades as reviewed changes, not silent patch bumps. Do not let Renovate auto-merge it.

Sequencing.

  1. Spike + schema review (2–3 days).
  2. Build a thin first-party abstraction — a small ReactionService / ReactsToContent interface in our domain layer that delegates to the package. All controllers, policies, and jobs call our interface; nothing outside that one file imports Turahe\Likeable\*.
  3. Ship to one model behind a feature flag; instrument p95 write latency and counter drift.
  4. Add queued listeners for analytics/notification off the like path.
  5. Schedule likeable:recount --type=like / --type=dislike nightly as a reconciliation job, with drift count as a metric.
  6. Expand to remaining models only after a clean month.
  7. Keep a written exit plan: the schema is ours, so the fallback is ~2–4 dev-days to reimplement like/unlike/toggle/count against the existing tables. That is the entire downside of adoption — worth stating explicitly in the ADR.

Operational Impact

Maintenance. Low steady-state effort, high variance risk. Budget roughly 1–2 engineer-days per quarter for version review, changelog reading, and drift monitoring. Assign a named internal owner — with no dependents and a single maintainer, "the community will catch it" is not an answer. Watch the changelog for breaking changes hidden in minor bumps; automated conventional-commit releases can move faster than a small team's review cadence.

Support. Community-only, GitHub issues, no SLA. Internal escalation path must be "we own it," which is another argument for the abstraction layer: when upstream goes quiet, we patch locally against a pinned version rather than forking.

Scaling. Read path is excellent — denormalised counters make likesCount a cheap join, and orderByLikesCount is index-friendly. Write path is the concern: each reaction is a row insert plus a counter upsert, and the counter row becomes a hot tuple on popular content. Under virality this serialises, and on MySQL/Postgres the failure mode is lock waits and occasional deadlocks, not corruption. Mitigations: retry-with-backoff on deadlock, queue-and-debounce counter updates for high-traffic objects, or read-through counting from the likes table for top-N ranking pages where exactness matters. Also enforce eager-loading conventions (with('likesCounter'), withCount) in code review — the accessor-based API invites accidental N+1 on every listing endpoint.

Failure modes and mitigations.

  • Counter drift after failed writes, bulk imports, or manual DB edits → nightly likeable:recount + drift alert.
  • Orphaned likes after user or content deletion → DB-level cascade, plus a cleanup job for pre-existing rows.
  • Listener exception aborting a like → queue listeners, or dispatch after commit.
  • Duplicate likes from double-submit or two open tabs → unique DB constraint plus idempotent toggling; do not rely on application check-then-write.
  • Counter deadlocks under concurrency → bounded retry, atomic increment, observability on retry rate.
  • Abandonment → pinned version, owned migrations, wrapper interface, documented reimplementation path.

Ramp-up. Negligible. The README is complete and example-driven; a mid-level Laravel developer is productive within half a day. The real onboarding content is the one-page convention doc we write: use like()/likeToggle() only via our ReactionService, always eager-load counters, never write to the likes tables directly, and how to run recount. Ship that with the first integration PR.

TPM recommendation. Adopt — but as a non-critical-path feature on low-stakes surfaces (comments, posts, articles), behind a first-party abstraction, with a pinned version, amended migrations, and a nightly reconciliation job. Do not put it on the critical path of ranking or moderation logic until it has survived a quarter in production and the provenance/maintainer questions are answered.

Weaver

How can I help you explore Laravel packages today?

Conversation history is not saved when not logged in.
Prompt
Add packages to context
No packages found.
gmostafa/php-graphql-client
xeviant/paystack
snowsoft/faker
meditationsteps/blogetc
animalyoung/laravel-influxdb
onix-solutions/sms-telera
lonely-lights/prosetta
oxygen/data
oxygen/core
jengo/base
xiloryx/log-collector
a21ns1g4ts/filament-stripe
la-php/laravel-admin
artisan-build/community-prompts
vleroy/smart
ayles-software/laravel-australian-public-holidays
cboxdk/laravel-id-spatie
cboxdk/laravel-id-billing
cboxdk/laravel-id-billing-bridge
simple-as-fuck/php-performance-log