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

Likeable Laravel Package

x-laravel/likeable

A Laravel package that adds like and dislike behavior to Eloquent models via a reusable trait, letting you attach reactions to posts, comments, or any model and query counts and liked items through a simple API.

View on GitHub
Deep Wiki
Context7

Technical Evaluation

Architecture fit. The package is a thin, trait-based polymorphic relationship layer — a good architectural fit for Laravel applications that already lean on Eloquent, service container config, model events, and the scheduler. It does not introduce a new persistence model or a service boundary; it adds two contracts (CanLike/Liker, HasLikes/Likeable), a pivot-style likes table, and a handful of query scopes. That is the right shape for a "likes" capability in a monolith or modular monolith, and it keeps the domain logic in the consuming models where most Laravel teams expect it. It is not a social-graph, reaction, or engagement-analytics product — if the roadmap includes reactions, weighted ranking, or feed ranking, treat this as a component rather than a platform.

Integration feasibility. High. Installation is additive: composer require, publish config, run migration, add traits, optionally set a default liker model. The withLikedBy() scope and isLikedBy() are the two features that decide whether this is usable in production list views — without them, every index page becomes an N+1 problem, so their presence in v1.0.0 is the difference between "demo-ready" and "ship-ready." like() returning the existing like on repeat makes the API effectively idempotent at the semantics level.

Technical risk. Concentrated in four places:

  1. Polymorphic type integrity. liker_type / likeable_type are string columns. If the app does not enforce a morph map, stored values are FQCNs and any namespace refactor silently orphans likes. Enforcing Relation::enforceMorphMap() should be a hard prerequisite, not a nice-to-have.
  2. Concurrency and uniqueness. "Liking again returns the existing like" describes application logic; double-tap or parallel requests can still race between the existence check and the insert. Confirm a database-level unique constraint on (liker_type, liker_id, likeable_type, likeable_id) exists or add it in the migration before rollout.
  3. Cleanup coverage. Cleanup appears to be driven by model delete events plus scheduled pruning. Deletes that bypass Eloquent — raw SQL, bulk query-builder deletes, GDPR erasure jobs, soft deletes, cascading FK operations — will strand rows until pruning runs. Soft-delete support is unstated.
  4. Event semantics. Liked/Unliked dispatched after commit is the correct choice, but it means consumers must tolerate at-least-once-ish delivery, ordering gaps, and no event on rollback. Anything that counts, notifies, or feeds a recommendation pipeline off these events needs idempotency keys; the payload shape isn't documented in the notes and should be treated as an unknown.

Key questions.

  • Are Laravel and PHP version floors stated (Laravel 10/11/12, PHP 8.1+)? Config-cache and scheduler behavior vary.
  • Is the unique constraint enforced in the shipped migration? Is the insert an upsert or a check-then-insert?
  • Do soft-deleted likeables/likers get pruned, and does likes() / likers() filter them?
  • Is pruning schedule registered by the package's service provider or does it require an explicit Schedule:: entry? Does it use onOneServer() for multi-node safety?
  • Are likers() and givenLikes() paginated or cursor-friendly, or do they return full collections?
  • What is the documented payload for Liked/Unliked, and are the events queued or synchronous after commit?
  • Licensing, maintainer bus factor, and support channel — v1.0.0 is the first stable tag, so there is no track record for deprecation policy.

Integration Approach

Stack fit. Assumes a conventional Laravel stack with MySQL/Postgres, queue workers, and the Laravel scheduler running. The package is framework-idiomatic and imposes no infrastructure: no Redis requirement, no external service, no search index. Configurable connection means it can be pinned to a specific database in a multi-database or read/write-split setup — worth using deliberately rather than defaulting, since like writes can be high-volume and should not compete with primary transaction traffic on a shared connection.

Migration path. Greenfield adoption is trivial: add traits to User and to the likeable models, publish config, migrate. For an application with an existing likes/favorites table, plan a real migration, not a swap: dual-write or backfill into the package's schema, normalize legacy type values to morph aliases, reconcile duplicates before adding the unique constraint, then cut reads over, then decommission the old table. Budget for a backfill of the row count plus the deduplication pass — that is the schedule risk, not the code change.

Compatibility. The two-combined-traits case (a model that is both liker and likeable) is the scenario to test explicitly, along with the default liker model config when an app has multiple user-like entities (User, Team, Organization). If the app uses UUID/ULID keys, verify the shipped migration's key column types before running it in a shared environment. If the app uses a morph map, confirm the package does not write raw class names.

Sequencing.

  1. Enforce morph map; publish config; review the migration (indexes, FK behavior, column types) before running.
  2. Add traits to one likeable model and one liker model; integrate withLikedBy() into the primary list view; measure query count.
  3. Add the like/unlike endpoints with authorization and rate limiting at the HTTP layer, since the package does not appear to provide them.
  4. Wire Liked/Unliked listeners (analytics, notifications) with idempotency handling; validate in staging that events do not fire on rolled-back transactions.
  5. Confirm pruning job registration, chunk size, and frequency against expected like volume; verify it runs on a single node.
  6. Roll out behind the first high-traffic surface, then expand.

Operational Impact

Maintenance. Small surface area — two traits, a few scopes, one table — which keeps maintenance cost low and upgrade risk modest. The counterweight is that a v1.0.0 has no upgrade history: the first minor release is where breaking changes usually surface, so pin the version and read changelogs rather than floating. The scheduled pruning job is the piece most likely to need tuning after go-live.

Support. No support tier is described in the release notes. For a capability that touches user-facing state and a scheduled job, decide internally who owns the likes table: schema changes, pruning health, and event contract changes need one named owner. If the package is a single-maintainer open-source project, plan for the possibility of vendoring or forking; the code footprint is small enough that this is a realistic fallback.

Scaling. Two pressure points. Write volume: each like is an insert plus a Liked event; a viral surface can produce bursty insert load and an event storm. Read volume: likers() counts and isLikedBy() checks per rendered item are the classic cost — withLikedBy() mitigates per-list state, but aggregate counts will need a cached counter (denormalized column, Redis, or a materialized count) rather than repeated count() queries. Pruning cost scales with orphan rate and chunk size; tune chunk size so the job stays inside its window without long locks. Polymorphic indexes must lead with the columns actually filtered in hot queries.

Failure modes to plan for.

  • Duplicate likes from request races if no DB-level unique constraint.
  • Orphaned likes from bulk deletes, raw SQL, GDPR erasure, or soft deletes that cleanup events never see.
  • Missed or duplicated downstream effects from Liked/Unliked if listeners are not idempotent.
  • Stale liked-state in list views if caches are not invalidated on Unliked.
  • Silent breakage after a model namespace refactor without a morph map.
  • Pruning job overlap or skipped runs on multi-node deployments without single-server scheduling.
  • Config cache staleness after changing the table, connection, or default liker model.

Ramp-up. For a Laravel developer, roughly half a day to working code and one to two days to a production-grade integration that includes authorization, rate limiting, eager-loaded liked-state, event consumers, and verified pruning. The real lead time is not engineering — it is product decisions the package deliberately leaves open: whether repeated likes are idempotent, whether users can see who liked them, whether counts are public and eventually consistent, how likes behave on soft-deleted content, and what the retention policy is for engagement events. Settle those before the first sprint, because they determine whether a cached counter and an event pipeline are in scope.

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.
payerurl/telegrambot-crypto-payment-instant-payout
dskripchenko/laravel-hybrid-search
riorizkyrainey/lara-ced
mehedimi/static-vel
zharp/zharp
nonsapiens/bigquery-model-sync
lgu-bayambang-ict-office/lgu-laravel-development-standards
andydefer/laravel-support
se7enxweb/flysystem
lampwick/laravel
jeslage/statamic-emojis
micahdshackelford/rmap-laravel
draftsmaninc/draftsman
square-bit/laravel-volition
himito/laravel-mailman
htinlynn/genius-helper
maco-studios/hephaestus
elmogy/larafast
xeviant/laravel-paystack
gorilladash/laravel-website-sdk