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

Tomato Category Laravel Package

tomatophp/tomato-category

Tomato Category is a category management package for TomatoPHP/Laravel apps, offering nested, sortable categories with an admin interface, API endpoints, and easy integration for organizing content across your projects.

View on GitHub
Deep Wiki
Context7

Technical Evaluation

Architecture fit. tomatophp/tomato-category is best understood as a schema + trait + admin-resource bundle, not a framework component. It gives any Eloquent model a polymorphic categorizable relationship backed by a single categories table with a type discriminator (category / tag / type) and an optional parent_id for shallow trees. For a TPM, the architectural decision it encodes is: one taxonomy table, discriminated by type, attached polymorphically. That is a reasonable, low-cost design for flat-to-shallow classification, and it is a poor fit for anything resembling enterprise taxonomy — no nested sets, no term merge/split, no audit trail, no search-grade faceting. Fit is high inside the Splade/TomatoPHP admin stack and low everywhere else; outside that stack this is roughly a day of hand-rolled migrations and a model, which removes the entire buy case.

Integration feasibility. Mechanically simple: composer require, publish config and migrations, migrate, add the trait to your model, register the resource. Realistically this is a 1–3 day task including verification, not the half-day the description implies — the trait name, pivot column names, and type literal casing all need confirming against src/Traits, database/migrations, and src/Models before anyone writes dependent code. The publish-order trap (migrate before publish → silently empty schema) is a known failure that costs an afternoon if it hits a junior engineer.

Technical risk. The headline risk is ownership, not code. Zero stars, zero dependents, and a last release of June 2024 (v1.1.10, a changelog-only patch bump) mean no field-tested upgrade path and no community signal on framework compatibility. Secondary risks are concrete and cheap to mitigate: stringly-typed discriminator values (silent empty results on casing mismatch), missing onDelete('cascade') leaving orphaned pivot rows, absence of a morph map causing class-name refactors to orphan every association, and no cache invalidation for any tree you cache yourself. Blast radius is contained only if this stays off customer-facing and revenue-critical paths — that is a scoping constraint to state explicitly, not delegate to engineering judgment.

Key questions to close before committing:

  • Which Laravel and PHP versions does the package actually support, and does that survive our next upgrade cycle?
  • Are we genuinely on Splade/TomatoPHP today, or is this an excuse to adopt it?
  • Is translation wired via spatie/laravel-translatable, or is per-locale labeling aspirational?
  • Does the published migration index the pivot and cascade on delete, or do we add both ourselves?
  • Who is the named owner of the vendored fork, and what is the review date?
  • Is our taxonomy need actually shallow, or will "just categories" grow into hierarchy and faceting in two quarters?

Integration Approach

Stack fit. Treat Splade/TomatoPHP as a hard precondition, not a preference. If the admin layer is Filament, Nova, or Backpack, stop here — those each have mature taxonomy plugins, and spatie/laravel-tags plus a resource is the better-supported bet. Adopting this package is never a reason to adopt the stack; it is a marginal-cost argument after the stack decision is made.

Migration path. Greenfield taxonomy is the clean case: define the vocabulary, seed idempotently with explicit slug + type, and build outward. Retrofitting an existing category or tag table is materially harder — you need a data migration into the polymorphic pivot, and a morph map enforced from day one (Relation::enforceMorphMap([...])) before a single pivot row exists, because adding it later orphans every association a class rename already touched. Design the exit path at the same time: put the package behind a thin repository or Taggable-style interface so controllers and views never call it directly. That converts a future rip-out from a rewrite into a contained change.

Compatibility. Pin the exact version ("1.x.y", not ^1.0) in composer.json. Verify the package's declared PHP/Laravel constraints against our supported matrix in the same PR that adds it, and record the tested combination in the repo. Publish the config and rebind models.category to our own subclass rather than editing vendor/ — that is the intended customization seam and the only thing that survives composer update at this release cadence.

Sequencing.

  1. Read the five locations (src/Models, database/migrations, src/Traits, config/, and the Filament/Http admin surface) — ~15 minutes, de-risks everything downstream.
  2. Spike on a throwaway branch: install, publish, migrate, attach one category and one tag to a model, confirm the type scoping behaves.
  3. Harden before feature work: morph map, type constants or a PHP enum, FK cascade (or soft deletes) on the pivot, typed relationships (tags(), categories()) as model methods so where('type', ...) never leaks into controllers or Blade.
  4. Write the pivot canary test — one feature test that attaches, syncs, detaches, and queries through the pivot with the morph map active. This is the artifact that makes a fork or upgrade survivable.
  5. Only then build UI on the resource, plus query patterns (whereIn subquery from the pivot for filtered listings, with/withCount on index screens to avoid N+1).

Steps 1–4 are the real cost; step 5 is the part that looks like progress.

Operational Impact

Maintenance. This is a fork-and-own decision, and the roadmap line item should read that way rather than "integrate a package." Budget a named owner, a vendored copy (or a pinned fork we control), and a periodic review date. MIT licensing makes the fork legal and cheap; single-maintainer abandonment makes it necessary, not optional.

Support. Assume no SLA: no ticket queue, no community answers, no security patching, no CVE process. The escalation path is internal. If a stakeholder asks "who do we call," the honest answer is "the engineer we assigned," and that answer needs a name in the plan.

Scaling. The polymorphic pivot is where performance degrades first. Index (categorizable_type, categorizable_id) and (type, slug) explicitly if the published migration doesn't. Prefer a whereIn('id', $idsFromPivot) subquery over whereHas on filtered listing pages, and withCount over loading collections when rendering counts. Any cached category tree is our responsibility to invalidate — wire an observer on our Category subclass to flush the cache key on save/delete, or staging will seed and then stare at a stale menu.

Failure modes to design against:

  • Silent type mismatch — 'Category' vs 'category' returns empty sets with no error. Mitigate with constants/enum.
  • Orphaned pivot rows on category delete when cascade is absent.
  • Orphaned associations when a model is moved to a new namespace without a morph map in place.
  • Stale cached navigation after seeding.
  • Missing admin menu item — check the config registration flag, then the panel provider's discovery path, then service-provider registration (Laravel 11+ bootstrap/providers.php).
  • Unannounced framework incompatibility surfacing during a Laravel upgrade rather than at install.

Ramp-up. Low for a competent Laravel engineer — the package is small enough to read in full. The onboarding cost that actually matters is institutional: write down the pinned version, the tested PHP/Laravel matrix, the morph map, the type constants, the canary test, and the fork owner. That document is the deliverable that turns a zero-star package into something the team can operate without the person who installed it.

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.
adachsoft/changelog-linter
adachsoft/collection
payerurl/telegrambot-crypto-payment-instant-payout
dskripchenko/laravel-hybrid-search
riorizkyrainey/lara-ced
mehedimi/static-vel
zharp/zharp
nonsapiens/bigquery-model-sync
lgu-bayambang-ict-office/lgu-laravel-development-standards
andydefer/laravel-support
se7enxweb/flysystem
lampwick/laravel
jeslage/statamic-emojis
micahdshackelford/rmap-laravel
draftsmaninc/draftsman
square-bit/laravel-volition
himito/laravel-mailman
htinlynn/genius-helper
maco-studios/hephaestus
elmogy/larafast