jelte-ten-holt/in-other-shops
A Laravel package for managing “in other shops” product availability. Register shops and product URLs, associate them with your catalogue, and render alternative retailer listings via a clean, configurable API. Useful for price comparison and marketplace-style product pages.
Architecture fit
This is a Laravel/PHP commerce support package (Filament admin schema + storefront actions + support helpers). v0.54.0 reinforces a contract boundary the package had only implicitly held: catalog display text is a model-level concern (getAttribute() via InteractsWithTranslations), not a database column. The new Support\ModelLabel::for(Model) makes that the sanctioned resolution seam, which is the right architectural move — it gives consumers one blessed path instead of ad-hoc pluck('name') / orderBy('name') calls. The fix itself is two call-site corrections; the durable change is the contract plus the doc rule.
Integration feasibility
Low effort, high urgency. No new dependencies, no config, no migrations, signatures unchanged. Column-backed consumers (in-other-worlds) see genuinely zero behavior change. Translatable-catalog consumers (bianka) are currently 500-ing on every order show/edit page — this is a hotfix, not a feature adoption, and should be scheduled as such.
Technical risk
where('name', …) from shipping. ModelLabel::for() is opt-in; there is no query-builder guard or static check.pluck('name','id') replaced by per-instance attribute resolution — plausible N+1 on order pages with large orderable option sets.where('name'/'description','like') and orderBy('name') clauses were removed; the notes don't state what replaces them. For translatable catalogs this could be a silent functional downgrade (search/sort stops working) rather than just a 500 fix.name → title → label → slug → "{alias} #{id}" chain never fails, which means a misconfigured model renders opaque keys in the admin UI with no error signal.WHERE 'name' … (always false) or no-ops instead of errors. 1065 green tests did not catch a production-wide 500, and two of the new tests passed against broken code until fixtures were rearranged. Green suite ≠ MySQL-correct.Key questions
ListBrowsables for translatable catalogs — is filtering restored, deferred, or dropped?ModelLabel::for() invoked per row on order pages? What's the query profile at realistic option counts, and is eager loading required?translations-backed catalogs and simply haven't reported the 500 yet?Stack fit Laravel + Filament admin + storefront actions. No new runtime requirements; PHP/Laravel support matrix unchanged.
Migration path
Straight composer bump. No schema changes, no data backfill, no config publication. The {alias}:{id} option-key format is unchanged, so persisted references (order line option keys, session carts) remain valid — that materially lowers migration risk.
Compatibility
bianka: required bump — order admin is broken without it.in-other-worlds: unaffected; normal cadence.translations-backed) before rollout is scheduled.Sequencing
translations-backed sites as at-risk.bianka (and any other translatable consumers) first; verify order show/edit and storefront search against MySQL with representative data.ModelLabel::for() in consumer-side custom Filament resources to converge on the shared seam.Maintenance
Small, contained surface: one support class, two call-site fixes, +10 tests, one doc section. docs/periphery.md → "Catalog text is not a column" is the durable artifact — fold it into the code-review checklist for anything touching browsable/cartable models.
Support Expect a short tail of reports from translatable-catalog consumers who hit the 500 pre-patch. Support script: "bump to v0.54.0, then verify against MySQL with real data." No new configuration means no configuration-support burden.
Scaling
Watch buildOrderableOptions() on high-volume tenants. Per-row attribute resolution on order pages with large option sets may add queries or memory where a single pluck previously sufficed. Benchmark at realistic catalog sizes rather than assuming parity.
Failure modes
where/orderBy on display fields reintroduces this class of outage — detectable only on MySQL.{alias} #{id} instead of names, with no error. Add logging/metrics when the terminal fallback fires.Ramp-up
Low. The fix is transparent to developers; the learning is the contract rule plus the SQLite caveat. Brief the team once on (a) ModelLabel::for() as the default way to render model labels, and (b) mandatory MySQL verification for changes touching browsable/cartable models.
How can I help you explore Laravel packages today?