sugar-agency/laravel-favorites
A Laravel package for adding favorites (bookmarks/likes) to Eloquent models. Likely provides polymorphic relationships and helper methods to favorite, unfavorite, and check favorited status. Verify exact API and features against the package's README before use.
Architecture fit
The package implements a well-understood domain pattern: a polymorphic many-to-many ("favoriteable") relationship plus a trait mixed into the user model. That is idiomatic Laravel — a HasFavorites-style trait, a Favorite pivot model, and one migration creating a favorites table with user_id, favoriteable_type, favoriteable_id, and timestamps. Fit against a conventional Eloquent-based monolith is therefore high, and the surface area is small enough that it can be reasoned about in a single code review rather than treated as a black box.
The genuine differentiator is not the relationship — most teams hand-roll that in under an hour — but the session-to-user transfer: guest favorites accumulate in the session and are claimed automatically on authentication. That is a real UX problem with a non-obvious correct implementation (deduplication on merge, idempotency, ordering, and the decision of what happens to the guest session afterward). If our product has anonymous browsing with any form of "save for later," this is the part worth evaluating, not the CRUD.
Fit degrades in two common architectures: (1) stateless API / SPA-with-token-auth backends, where there is no server session to seed guest favorites from; and (2) multi-tenant or multi-guard systems, where the hardcoded user_id foreign key and default guard assumption usually need overriding. Both are workable, but they move the package from "install and go" to "fork and adapt."
Integration feasibility
Integration is a composer require plus a migration plus a trait import — realistically half a day for a first working slice in a spike branch. The feasibility question is not technical difficulty but provenance: zero stars, zero dependents, and a zero score mean the package has no observable production validation. We would be the first substantive adopter in the public record. That does not disqualify it, but it changes the adoption mode from "dependency" to "vendored code we now own."
Technical risk
Key questions
(user_id, favoriteable_type, favoriteable_id), and is the toggle operation idempotent under concurrent requests?users table name, and how configurable is that?Stack fit
Strong fit for a server-rendered Laravel application (Blade/Livewire/Inertia) with session-based auth and a logged-in user model. Weak fit for a decoupled API backend, where the session-transfer feature is unreachable and we would be adopting a package for its least interesting half. If our architecture is API-first, the honest recommendation is to implement the two tables and trait internally and skip the dependency.
Migration path
Treat this as a fork-first adoption, not a composer require and move on:
favorites is a plausible name for an existing or future domain table.Because the package creates its own table and touches only the user model via a trait, the migration is additive and reversible. Rollback is a dropped table plus a trait removal — low blast radius.
Compatibility
Verify against our pinned Laravel and PHP versions, our session driver (database/redis drivers are fine; the concern is payload shape, not storage), and our auth guard configuration. Also confirm compatibility with whatever the existing user model already mixes in — trait collisions on method names like favorites() or hasFavorited() are the most likely day-one breakage in a mature codebase.
Sequencing
Spike (1–2 days) → fork and harden with tests (3–5 days) → ship behind a feature flag to a single content type → expand to additional favoritable models → instrument and review at 30 days. Gate the expansion on observed transfer-merge behavior in production, since that is the component with the least external validation and the highest user-visible consequence.
Maintenance
Assume we own this code. With zero dependents, there is no community pressure to patch it, no issue-tracker signal to read, and no realistic expectation of timely upstream fixes. Budget a standing line item for Laravel major-version upgrades and security review — small, but nonzero and permanent. The mitigating structure is that a fork of ~300 lines is cheaper to maintain than most dependencies we already carry.
Support
No meaningful support channel. Debugging falls entirely to us; there is no downstream corpus of Stack Overflow answers or GitHub issues to lean on. This is acceptable for a package this small and this close to a well-known pattern, and unacceptable if the team adopting it is junior and expects the dependency to be self-explaining.
Scaling
Favoriting is write-light and read-heavy, and the read pattern is the risk. Per-item "is this favorited" checks in a list view are a classic N+1 — the package will not solve that for us, so we need eager loading or a preloaded ID set. On the write side, high-frequency toggle traffic concentrates on a single index and can deadlock without a unique constraint enforcing idempotency. At scale, per-object favorite counts belong in a denormalized counter, not a COUNT(*) on the polymorphic table. None of these are package defects; they are design decisions the package leaves open, and we should not mistake its silence for a solution.
Failure modes
favoriteable references; surfacing them as broken links is a user-visible defect.Ramp-up
Low for anyone fluent in Eloquent relationships — a competent Laravel engineer reads the whole package in an afternoon. The learning cost is concentrated in the transfer semantics, which are undocumented in proportion to their subtlety. Plan for one engineer to own the fork, write the transfer tests, and be the reference point; do not distribute this across the team as a background task.
Verdict
Adopt only as a vendored, internally-owned fork, and only if guest-to-user favorite transfer is a product requirement we would otherwise hand-build anyway. If we are API-first, or if the feature is merely "nice to have," the correct call is to skip the dependency and implement the ~150 lines directly — we would be writing most of the hardening work regardless, and we would avoid carrying an unmaintained dependency for a pattern we already understand.
How can I help you explore Laravel packages today?