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 User Guest Like Laravel Package

kilobyteno/laravel-user-guest-like

A Laravel package that lets both authenticated users and guests like your Eloquent models. Add the trait, and get simple methods for liking, unliking, and checking likes, with guest likes tracked automatically and no extra setup required.

View on GitHub
Deep Wiki
Context7

Getting Started

  1. Install into a Laravel 12/13 app:

    composer require kilobyteno/laravel-user-guest-like
    

    Version pinning: 1.5.0 adds Laravel 13 support and drops Laravel 11. On an L11 codebase stay on ^1.4, or upgrade the app first.

  2. Publish and run the migration (the package ships a likes migration — publish it rather than editing the vendor copy, so you can add indexes):

    php artisan vendor:publish --tag="user-guest-like-migrations"
    php artisan migrate
    
  3. Add the trait to every model that can be liked (e.g. Post, Comment):

    use Kilobyteno\UserGuestLike\Traits\Likeable;
    
    class Post extends Model
    {
        use Likeable;
    }
    
  4. Where to look first: the package README for the exact trait/method names, then src/Traits/ and the published migration. The migration tells you more about behaviour than the docs — specifically how a guest is identified (session ID vs. IP) and which columns form the uniqueness constraint.

  5. First use case — a toggle endpoint for a like button:

    Route::post('/posts/{post}/like', function (Post $post) {
        $post->toggleLike(); // or like()/unlike(); confirm names in the README
        return back();
    });
    

    Guests work out of the box because the package resolves the current liker from the session when auth()->check() is false — no login wall required.

Implementation Patterns

Treat likes as a toggle, not two endpoints. One POST /like route that delegates to the package's toggle keeps the UI simple and makes double-clicks idempotent-ish. Return the fresh count so the front end can update without a reload:

return response()->json([
    'liked' => $post->isLikedByCurrent(), // confirm method name
    'count' => $post->likes()->count(),
]);

Eager-load counts for index pages. This is the single biggest performance lever:

$posts = Post::withCount('likes')->paginate(20);
// Blade: {{ $post->likes_count }}

Never call $post->likes()->count() inside a loop — that's an N+1 per row.

Guard against "did I like this" N+1 too. If each card renders a filled/unfilled heart, either eager load the current user's liked IDs once and pass a set to the view, or expose a scoped query in a service class:

$likedIds = Like::where('user_id', auth()->id())
    ->where('likeable_type', Post::class)
    ->pluck('likeable_id')
    ->flip();

Livewire / Inertia front ends. Keep the component dumb: dispatch to the package, then $this->post->refresh() or return an Inertia prop with the updated count. Avoid caching the count in a public property that can drift from the DB after another user likes the same post.

Merge guest likes on login. In your Login/Registered listener, before regenerating the session, grab the guest's likes by the package's guest key and re-point them at auth()->id(). De-duplicate against existing rows or the unique index will throw. This is the pattern that makes the "guest can like, then sign up" funnel work without losing data.

Rate-limit the endpoint. Guest likes are cheap to spam. A throttle:30,1 middleware on the toggle route plus a DB unique constraint is a reasonable baseline.

Testing. Use actingAs($user) for authenticated cases and a plain $this->post(...) for guest cases — the guest identity will persist across requests in the same test because the session does. Assert on the DB with assertDatabaseHas('likes', [...]) rather than on rendered HTML.

Gotchas and Tips

  • Version constraint is the real breaking change in 1.5.0. Nothing in the public API moved, but composer update on a Laravel 11 app will now fail resolution (or, worse, silently pin you to 1.4.x if the constraint is loose). Check composer why-not kilobyteno/laravel-user-guest-like 1.5.0 before blaming the package.
  • Guest identity is session-bound, not IP-bound. Session regeneration on login, or a user clearing cookies, detaches pending guest likes. If your product cares about guest like counts (e.g. a public popularity metric), decide early whether anonymous likes are real votes or just UI state — and consider requiring auth for anything you rank on.
  • Unique constraint races. Two tabs toggling simultaneously can hit a duplicate-key error instead of a clean toggle. Wrap the write in firstOrCreate-style logic or catch QueryException with SQLSTATE 23000 and re-read the state.
  • Polymorphic cleanup. likes rows survive delete() on the likeable model unless you add a deleting observer or a DB-level cascade. Orphaned rows inflate counts on re-used IDs (rare, but it happens with soft deletes + re-seeding). Add a scheduled prune job for likeable_type values no longer in use.
  • Polymorphic type string length. If you use a custom morph map, publish the migration and confirm likeable_type is string(255) — truncated class names produce silently non-matching queries.
  • Publish the migration, don't rely on the vendor one. You'll want an index on (likeable_type, likeable_id) and on (user_id, likeable_type, likeable_id) for the "has liked" lookups; the shipped migration may not include both.
  • Counting is not free at scale. If a post's like count appears on a high-traffic page, denormalise into a likes_count column updated on write, or cache with a short TTL and accept slight staleness. withCount is fine to hundreds of thousands of rows, not millions.
  • Extension points: the package's Like model is the natural place to hook — bind a subclass via config if the package exposes a model config key, so you can add soft deletes, a source column, or an event listener without forking. Fire your own PostLiked/PostUnliked events from your controller rather than expecting the package to.
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.
uni-method/symfony-lib
tacticmedia/scim-server-bundle
neika-ai/symfony-bundle
mattleads/agent-publishing-bundle
glavweb/framework-bundle
glavweb/extra-bundle
glavweb/api-bundle
glavweb/admin-bundle
adachsoft/api-version-bundle
elsayed85/laravel-api-exceptions
ouhssini/laravel-demo-mode
daworks/ncloud-outbound-mailer-driver
gp247/cms
ignibyte/aic-gates
nexa-merchant/blog
novasa/laravel-language-center
opencage/geocode
adolfoholzer/parameters
livenetworks/ln-starter
cgv/localized-resource