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

Laracombee Laravel Package

amranidev/laracombee

Laracombee is a Laravel package offering a simple, Laravel-friendly interface to the Recombee recommendation API. Manage users, items, interactions, and personalized recommendations for e-commerce, media, and marketplace applications.

View on GitHub
Deep Wiki
Context7

Getting Started

Install and let package discovery register the provider:

composer require amranidev/laracombee
php artisan vendor:publish --tag=laracombee-config

Then set the minimum config in config/laracombee.php (or .env):

'database' => env('RECOMBEE_DATABASE'),
'token'    => env('RECOMBEE_TOKEN'),
'protocol' => 'https',      // default is http — change this
'region'   => 'eu-west',
'timeout'  => 2000,
'user'     => \App\Models\User::class,
'item'     => \App\Models\Book::class,

The user and item keys matter: the Artisan commands (laracombee:migrate, laracombee:seed, etc.) resolve these models. Next, declare the schema on each model with the static $laracombee property — this is the source of truth for Recombee properties:

public static $laracombee = [
    'name' => 'string',
    'age'  => 'int',
];

Then push the schema and backfill existing rows:

php artisan laracombee:migrate user
php artisan laracombee:migrate item
php artisan laracombee:seed item --chunk=250

First real use case: hydrate a recommendation list for a known user.

$user = User::findOrFail($id);

$response = Laracombee::recommendTo($user, 10)->wait();

$ids = collect($response['recomms'])->pluck('id');
$books = Book::whereIn('id', $ids)->get();

Once that works, add the write side — fire addDetailView / addPurchase / addRating as users interact, otherwise recommendations are just popular-items noise.

Implementation Patterns

Wrap the client in your own service. Laracombee is a thin facade over the Recombee SDK; don't scatter Laracombee:: calls across controllers. Create App\Services\Recommender that owns recommendation fetching, fallbacks, and caching. It makes tests trivial and lets you swap engines later.

Read calls execute immediately; write calls return a request you must send. This asymmetry is the single most important pattern:

// Write: build request, then send + handle + block
Laracombee::send(Laracombee::addPurchase($userId, $itemId))
    ->then(fn () => null)
    ->otherwise(fn ($e) => Log::warning('recombee', ['e' => $e]))
    ->wait();

// Read: already dispatched, just wait
$response = Laracombee::recommendTo($user, 10, ['scenario' => 'homepage'])->wait();

Track interactions from domain events, not controllers. Register listeners or model observers and push to Recombee off the request path:

// app/Observers/OrderObserver.php
public function created(Order $order): void
{
    dispatch(new SyncPurchaseToRecombee($order->user_id, $order->book_id));
}

In the job, use cascadeCreate => true in the options array so a purchase from a user not yet in Recombee still lands:

Laracombee::addPurchase($userId, $itemId, ['cascadeCreate' => true, 'timestamp' => now()->toIso8601String()]);

Batch anything bulk. Backfills, imports, and re-syncs should use addUsers / batch rather than N individual wait() calls:

$requests = $books->map(fn ($b) => Laracombee::setItemValues($b->id, [
    'title' => $b->title,
    'price' => (float) $b->price,
]));

Laracombee::batch($requests->all())->wait();

Chunk to a few hundred requests per batch and run it in a queued job; large synchronous batches will blow past the timeout setting.

Treat $laracombee as a migration file. Add properties to the static array, then run laracombee:migrate item as part of deploy. For one-off changes, use the CLI instead of editing the model:

php artisan laracombee:add isbn:string published_at:timestamp --to=item
php artisan laracombee:drop isbn --from=item

Customize the recommendation request per surface. Pass a scenario and ask for properties back to avoid an N+1 on hydration:

$response = Laracombee::recommendTo($user, 12, [
    'scenario'         => 'product_detail',
    'returnProperties' => ['title', 'price', 'image'],
    'filter'           => "'price' < 50",
]);

Multiple databases. For a separate reporting or staging Recombee DB, scaffold a class and use it directly (or bind it in a service provider):

php artisan laracombee:new ReportingLaracombee
$reporting = app(\App\Laracombee\ReportingLaracombee::class);
$reporting->recommendItemsToUser($id, 5)->wait();

Extend AbstractRecombee when you need real control — centralised retries, metrics, or error translation:

class MyRecombee extends AbstractRecombee
{
    public function send(Request $request)
    {
        return $this->client->send($request)
            ->then(null, function ($e) {
                report($e);
                throw $e;
            });
    }
}

Gotchas and Tips

  • Forgetting ->wait() silently drops the request. The SDK is async; a promise that's never awaited may never complete, and exceptions in otherwise never fire. In PHP-FPM this is the #1 source of "why is my data missing" bugs. Always terminate the chain with wait() on writes.
  • Never call send() on a recommendation. recommendTo, recommendItemsToUser, and recommendUsersToUser dispatch immediately and return a promise. Wrapping them in send() will fail or double-send.
  • Default protocol is http. Set https in production; the private token travels in the request path/headers and you don't want it on the wire in plaintext.
  • timeout defaults to 2000 ms. Fine for a single interaction, too tight for batches or seeding. Raise it in config for queue workers and console commands.
  • laracombee:reset is a full database wipe — users, items, properties, interactions, series. Guard it: never expose it as a deploy step, and consider blocking it in production via a check in your deploy script or an environment gate.
  • Property types in $laracombee must match what you actually send. Sending "42" for an int property or a string date for a timestamp leads to rejected requests that are easy to miss inside a batch. Cast explicitly in your sync jobs.
  • Renaming or removing a property from the static array does nothing. You must run laracombee:drop explicitly. Stale properties accumulate silently.
  • IDs must be stable and consistent. Laracombee keys users/items by the model's key. If you migrate from auto-increment ints to UUIDs, every existing Recombee record is orphaned — plan a re-seed.
  • Use cascadeCreate on interaction writes for anything that could arrive before the user/item sync (signups, guest checkouts, rapid imports). Otherwise you get "user not found" errors that look like package failures.
  • addUser vs setUserValues vs mergeUsersWithId. addUser creates; setUserValues updates fields on an existing user; mergeUsersWithId folds an anonymous/guest ID into a real one — the standard pattern for "guest browses, then logs in."
  • Handle empty recomms. New users, cold items, and over-restrictive filters all return an empty array. Always have a fallback (popular items, recent items) rather than an empty shelf.
  • Config caching. After php artisan config:cache, edits to config/laracombee.php won't take effect until you re-cache. This bites people during initial setup when they're toggling the database ID.
  • The generated custom class from laracombee:new is not auto-bound to the container. Instantiate it directly or add an explicit binding in a service provider — don't assume Laracombee::class resolves to it.
  • Keep Recombee out of the request cycle for writes. A slow or failing Recombee call should never fail a checkout. Fire interaction events into a queue, log otherwise failures, and let recommendations degrade gracefully.
  • Small package, single maintainer (0 dependents). Pin the version in composer.json, keep all direct Laracombee:: usage behind your own service class, and cover it with a fake/offline test so an upstream SDK bump is a one-file fix.
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.
htinlynn/genius-helper
maco-studios/hephaestus
elmogy/larafast
xeviant/laravel-paystack
gorilladash/laravel-website-sdk
martialbe/flysystem-oss
chondal/3312client
jeroen-g/flickr
opscale-co/nova-genbi
itsjustvita/laravel-retention
tequilarapido/trackit
gregsphotography/site-builder-filament
cabaoctavio/laravel-query-log
gregsphotography/site-builder-components
io-digital/clickatell
snowsoft/laravel-admin
oxygen/auth
relicsoftware/barakah-payment-gateway
tobya/work-with-composer
equipc/laravel-email-validator