tourze/product-ranking-bundle
A PHP bundle that adds product ranking to your application, providing the core structures and services needed to score, sort, and surface products by popularity or relevance. Use it to build leaderboards, best-seller lists, and ordered search results without writing ranking logic from scratch.
Reality check on 0.0.1: the only artifact published with this release is a changelog link. There is no README excerpt, no documented API surface, and no migration or config reference in the release notes. Treat 0.0.1 as a source-reading exercise, not a documented integration.
0.0.x release, Composer will treat it as unstable-ish semver (0.0.1 has no backward-compatibility promise). Require "tourze/product-ranking-bundle": "0.0.1" with an exact constraint, and commit the lock file.composer.json first. Confirm three things before writing any code:
type field — symfony-bundle versus library tells you whether Laravel's package auto-discovery will do anything for you;require block — whether it pulls in symfony/* components, Doctrine, or nothing framework-specific;use (the package name suggests Tourze\ProductRankingBundle, but verify rather than assume)..github/workflows/, composer.json require-dev, and any tests/ directory. With no docs, the test suite is the specification. Tests tell you the intended data shape, the ranking algorithm's tie-breaking behaviour, and whether persistence is expected to be supplied by you or by the bundle.src/. Scan for a service provider or Symfony *Extension class (the config entry point), any Repository/Ranker/Calculator/Sorter classes (the actual API), and any Resources/config/ or config/ directory (default options and their keys).First use case to attempt: a read-only ranking query — take a collection of products with a numeric score, feed it to whatever ranking/sorting service the package exposes, and render the top N. Do this before you touch persistence or write paths, because a 0.0.1 ranking package is most likely to be a pure scoring/sorting library with the storage layer left to you. If that read-only path works, you have learned the core contract; if it requires database tables that don't ship, you have learned that immediately and cheaply.
Wrap it, don't sprinkle it. Put a single ProductRanking adapter class in app/Services/ that owns every call into the package. On a 0.0.x dependency this is not ceremony — it is your upgrade insurance. If 0.0.2 renames a method, you edit one file.
Bind the contract in a service provider. If the package ships interfaces, register concrete bindings in AppServiceProvider::register() rather than resolving classes from the container inline. This is also where you inject your ranking configuration (weights, score sources, limits) so the package stays framework-agnostic and your app owns the policy.
Compute on write, read from a materialised table. Ranking at request time is the pattern that ages badly. Store a rank or score column (or a dedicated product_rankings table) and recompute on a schedule or on relevant model events. The package almost certainly gives you the ordering logic but not the storage — so you own the table, the index, and the recompute trigger.
Use a queued job for bulk recomputation. If ranking is O(n log n) over a full catalogue, a queued RecalculateProductRankings job with WithoutOverlapping middleware prevents a redeploy or a double-click from stacking concurrent recomputes over the same rows.
Scope by tenant/store explicitly. Multi-tenant catalogues break naive ranking because a global top-10 leaks cross-tenant data. If the package's API takes no scope parameter, apply scope in your adapter — filter the candidate set before ranking, never after.
Keep a deterministic tie-breaker. Ties in score are where ranking bugs hide. Always append a stable secondary sort (e.g. product_id ASC) after the package's ordering so paginated results don't reshuffle between page 1 and page 2.
Feature-flag the rollout. Given undocumented behaviour, ship behind a config flag or Laravel Pennant feature so you can compare package output against your existing ordering in production before flipping over.
extra.laravel.providers auto-discovery will silently do nothing if that key is absent. Check composer.json; if there is no Laravel provider, you may need to register services manually or write a thin bridge. Budget for this — it is the single most likely source of a "nothing happens" first hour.php artisan vendor:publish) or a Symfony Configuration class. If neither exists, configuration is either constructor arguments or absent, and hard-coded defaults are baked into the code — grep for magic numbers.Migrations/ or migrations/ directory; if empty, you are writing the schema.0.0.1 → 0.0.2 bump can legitimately rename classes, change return types, or invert sort direction — under semver that is allowed in the 0.0.x range. Use an exact constraint and read the diff before bumping. Treat every upgrade as a minor review task.store_id, rank) — the read path is almost always "top N within scope", and without the composite index you will table-scan once the catalogue grows.How can I help you explore Laravel packages today?