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 Model Recommendation Laravel Package

umutphp/laravel-model-recommendation

A Laravel package that adds recommendation capabilities to your Eloquent models. Track user interactions, then retrieve suggested models using built-in algorithms—ideal for powering "you may also like" features with a simple, expressive API. Includes migrations and traits to get started fa...

View on GitHub
Deep Wiki
Context7

Getting Started

The package provides model-to-model recommendations (think "related posts", "you may also like") by scoring how similar two Eloquent models are and persisting the results, so serving a recommendation list is a simple relation lookup rather than a query-time computation.

Minimal setup:

  1. composer require umutphp/laravel-model-recommendation — as of v0.4.0 this resolves against Laravel 10, 11 and 12 (v0.3.x stopped at 11), so it is safe to pull into a Laravel 12 app.
  2. Publish the package assets (php artisan vendor:publish and select the package's provider/tag) to get the config file and the recommendations migration, then run php artisan migrate.
  3. Add the package's trait to the model(s) that should be recommendable and implement the method that exposes the data used for similarity (the tag/attribute source).
  4. Run the package's generation command (see php artisan list for the recommendation:* entry) to backfill scores, then read them back through the relation the trait adds to the model.

Look first at:

  • The published config file — it is where you register which models get processed, the similarity threshold and how many recommendations to keep per model. This is the single file you will edit most.
  • The trait itself (short, worth reading end to end) to confirm the exact method name and return shape expected for the similarity source.
  • The generation command's --help output, since the flags (model filter, truncate/rebuild, chunk size) determine how you wire it into a scheduler.

First real use case: a Post model with tags. Expose the tag IDs from the similarity method, run generation once, and render $post->recommendations in a sidebar. That gives you a working end-to-end loop in under ten minutes and surfaces immediately whether your data is dense enough for the scores to be meaningful.

Implementation Patterns

Pick your similarity source deliberately. The quality of everything downstream is determined by what the trait's similarity method returns. Tags/categories are the easy path; for content models without tags, synthesise the signal (e.g. derive a tag set from category + author + keyword extraction) rather than feeding in raw free text that will never overlap.

Generate out-of-band, never on save. The generation pass compares models against each other, so it is O(n²)-ish and absolutely should not live in an updated observer. Schedule it — nightly for small datasets, hourly with a chunked/limited model scope for large ones — and treat the recommendations table as a materialised view.

Read through the relation with a limit and eager load. Serve $post->recommendations()->limit(5)->get() (or the configured limit) and eager load nested relations the card component needs. Because the rows are precomputed, this is a cheap indexed lookup; put a short cache TTL on the rendered list if the page is hot.

Stale-row hygiene. When a model is deleted or its tag set changes materially, its recommendations and the rows pointing at it go stale. Pair the generation run with a cleanup step, and prefer a full rebuild for the affected model over incremental patching unless your dataset is large enough that the full pass hurts.

Multi-tenant / per-user recommendations. The default flow is global per-model similarity. For personalised lists, keep the package output as the candidate pool and apply your own user-level filtering or re-ranking on top, rather than trying to force user context into the package's scoring.

Testing. Use RefreshDatabase with an explicit Relation::enforceMorphMap() in tests so the polymorphic model_type/recommended_type columns are stable, and assert on the relation's contents after running the generation command inside the test rather than mocking the scorer.

Gotchas and Tips

  • v0.4.0 is a compatibility release, not a behaviour change. The only shipped change is Laravel 12 support. Upgrading from v0.3.3 should require nothing beyond a composer update; there are no documented breaking changes or deprecations. If you are on Laravel 12 this is the first usable version, so pin ^0.4.
  • Check the composer constraint before upgrading a Laravel 12 app that was stuck on v0.3.x. If you had a conflict or a pinned 0.3.* in composer.json, remove it, otherwise the new illuminate/support range will not resolve.
  • Empty recommendations are almost always a data problem, not a package problem. If the similarity source returns an empty array or everything shares zero overlap, you get nothing back with no error. Log the size of the similarity source per model during the first generation run.
  • Threshold tuning is where the perceived quality lives. A threshold that is too loose surfaces unrelated models; too tight and half your catalogue has an empty sidebar. Always render a fallback ("popular in this category") so the UI never breaks on a cold model.
  • Morph map discipline. The recommendations table is polymorphic. If you introduce Relation::enforceMorphMap(), do it before generating, or previously stored class-name strings will no longer resolve.
  • Large rebuilds will spike the DB. The generation pass issues a lot of writes. Run it in a queue worker with a chunk size, wrap it in a transaction per chunk rather than one giant transaction, and avoid running it concurrently with itself (use withoutOverlapping() on the scheduled task).
  • Extension points are the config and the similarity method. There is no pluggable scoring-strategy interface worth relying on — if you need a custom algorithm, fork the scorer or compute scores yourself and write into the package table. Keep the table shape and you keep the relation for free.
  • Verify names against the README for v0.4.0. The package is small and its public surface (trait name, command signature, config keys) is the thing to confirm on install; don't assume from older blog posts, several of which predate the Laravel 10/11/12 support matrix.
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.
pharaonic/laravel-notification-dependencies
beautinow/translug
dev-brainiac/bot-cloaked
octoberrain/html
octoberrain/extension
octoberrain/exception
octoberrain/contracts
frankyso/ipaymu
3mdikram/worldmoneywords
snowsoft/config
itmosoft/laravel-subscriptions
larva/laravel-ai-qwen
adachsoft/api-version-bundle
cgv/localized-resource
noith/settings
kda/laravel-package
kda/filament-dynamic-navigation
bypersoft/signbox
pairus/product-data
fayne/laravel-filament-cms-core