Laravel Packagev13.xMIT License0+ downloads

Favorites: One favorite per pair, guaranteed by the database

Add CanFavorite to the model that favorites and HasFavorites to the model that is favorited, run one migration, and write $user->favorite($post). A unique index keeps each pair to one row, even when two requests arrive at once.

$composer require pharaonic/laravel-favorites
Key Features

Favorites that stay correct

A small API on top of native Eloquent relations.

Results That Say What Changed

favorite() and unfavorite() return true only when they changed the table, so a repeated click is easy to tell apart.

Unique by the Database

A unique index on the four columns keeps each favoriter and favoritable pair to one row, under concurrent requests too.

Any Model Favorites Any Model

Users, teams or bots favorite posts, comments, products or each other. One model can use CanFavorite and HasFavorites together.

Native Counts and Eager Loading

withCount('favorites'), with('favorites.favoriter') and whereFavoritedBy($user) run in SQL, without loading every favorite.

Integer, UUID and ULID Keys

Ids are stored as strings, so models with different key types share one table, with morph map aliases respected.

Clean Deletes

Deleting a model deletes its favorites; a soft delete keeps them, so a restored model keeps its favorites.

A quick look

A user favorites a post, and the post page shows its count.

routes/web.php
1use App\Models\Post;
2 
3Route::post('posts/{post}/favorite', function (Post $post) {
4 $created = request()->user()->favorite($post);
5 
6 return response()->json([
7 'created' => $created, // false when it was already favorited
8 'favorites' => $post->favorites()->count(),
9 ]);
10})->middleware('auth');
11 
12Route::get('posts', function () {
13 return Post::withCount('favorites')->latest()->paginate();
14});
FAQ

Favorites Questions

Quick answers about installing and using Favorites.

What is Favorites?

Let any Eloquent model favorite any other: favorite, unfavorite and toggle with results that say what changed, a unique index that keeps each pair to one row, and native relations for counts and eager loading. It's a free, open-source Laravel package by Pharaonic.

How do I install Favorites?

Run composer require pharaonic/laravel-favorites in your project's root directory, then php artisan migrate.

What does Favorites require?

The latest release requires PHP 8.3+ and Laravel 13.

Does the favoriter have to be a user?

No. Any Eloquent model with the CanFavorite trait can favorite, and any model can be favorited. Nothing in the package reads the authenticated user.

What happens when the same user favorites twice at the same moment?

One request creates the favorite and returns true; the other finds the unique index in its way and returns false. The table never holds two rows for the pair.

Can I use it with UUID or ULID models?

Yes. Ids are stored as strings of up to 64 characters, so integer, UUID and ULID models can favorite each other in the same table.

Can I use it next to Laravel Likes or Laravel Follows?

Yes. A favorite is its own row in its own favorites table, with its own traits, model and events, so the three packages can be installed together without sharing records.

Is Favorites free to use?

Yes. Favorites is open source under the MIT license, so you can use it in personal and commercial projects.

Where can I find the Favorites documentation?

Read the Favorites documentation for setup, configuration, and usage examples.

How do I report a bug or contribute to Favorites?

Open an issue or a pull request on GitHub, or ask in the Pharaonic Discord.

Ready to dig in?

Read the full documentation for installation, configuration, favoriting and unfavoriting, relations, counts and filters, morph maps and key types, events, deletes and soft deletes, concurrency, the API reference, examples, and troubleshooting.