illegal/laravel-utils
A small collection of helper utilities for Laravel applications, bundling convenient functions and traits for everyday development tasks. Lightweight, easy to install, and designed to drop into any Laravel project without extra configuration.
Architecture fit. illegal/laravel-utils remains a grab-bag "collection of useful tools" — the archetypal cross-cutting helper bundle (global helper functions, collection/string macros, Blade directives, validation rules, a service provider). That shape has no clean architectural owner: it isn't domain-scoped, it isn't a bounded capability, and it inserts itself into every layer via globals and macros.
v1.2 does not change that diagnosis, but it does widen the blast radius: the Sortable trait is a Livewire/UI-layer concern, so the package now spans backend helpers and frontend component behaviour. That is a worse architectural fit than before, not a better one — a single dependency now touches the service layer and the Livewire component lifecycle, two areas with different upgrade cadences and different owners. It remains a tolerable leaf dependency in a small single-team Laravel app and a poor fit anywhere the dependency graph is governed. Fit rating: low-to-moderate, trending low.
Integration feasibility. Still technically trivial — MIT, Composer-installable, auto-discovered. A trait is a comparatively safe addition in isolation: it is opt-in, only loaded when a component uses it, cannot shadow application code the way a global function or macro can, and adds no boot-time registration for non-users. Integration effort for v1.2 specifically is minutes.
The new work is verification, not integration: we must determine whether Livewire is a hard require or a suggest/conditional in composer.json. If v1.2 makes Livewire a hard dependency, the package is now disqualified for any non-Livewire service in our portfolio — that is a meaningful change from the prior assessment.
Technical risk.
Sortable trait is a namespaced, opt-in symbol and therefore collision-safe by construction — better hygiene than the global-function layer. It does not reduce existing macro/global collision risk, which is unchanged.Key questions. Is Livewire a hard requirement in v1.2's composer.json, and if so at which constraint? Does Sortable target Livewire 2, 3, or both? What public properties does it introduce, and are they serializable scalars or Eloquent models? Does it ship JS/Alpine assets that need publishing or a build step? Does the trait assume a specific collection key or an order column? Does our Livewire version match, and are we on Livewire at all? Do any of our apps already pull this package transitively — and did v1.2 change that set? And the prior questions that remain unanswered: enumerated API surface, global/macro collision audit, maintainer reachability and transfer appetite, archived-package policy.
Stack fit. Acceptable for a Laravel 9/10 monolith with a small team and no formal upgrade SLA — now with the caveat that it is only acceptable if we are already a Livewire shop on a matching major. For any app without Livewire, v1.2 is dead weight at best and an uninstallable hard dependency at worst. Still unacceptable as a dependency of anything we publish or share internally, since it becomes transitive for every consumer and now drags a Livewire constraint along with it.
Migration path. Unchanged in direction: do not add it as a runtime dependency. Inventory helpers, copy into app/Support with the MIT header and attribution, test, own it. If the Sortable trait is the thing we actually want, the same logic applies with a smaller scope — a sort trait is a few dozen lines over a collection sort and is cheaper to own than to inherit. For legacy adoption: pin the exact tag, wrap call sites behind our facade or namespaced helper, schedule removal. Sequence unchanged: inventory → extract → vendor + test → swap → drop requirement → delete.
Compatibility. Matrix expands. Previously PHP 8.2–8.4 against Laravel 10–12. Now add Livewire major(s) — verify against our pinned Livewire version, and explicitly test the trait's hydration and re-render path, not just its sort output. Inspect v1.2's composer.json diff against v1.1 first; that is a ten-minute check that determines whether the rest of the matrix matters for non-Livewire apps. Because upstream is still effectively unowned, every future Livewire or Laravel major remains our cost by definition — v1.2 adds a second framework axis to that fork-maintenance budget.
Sequencing. (1) Diff v1.1 → v1.2 composer.json and confirm whether Livewire is required or suggested — if required and we have no Livewire, stop here. (2) Inventory the used API surface, now itemising the Sortable trait separately as a high-interest candidate. (3) One-to-two-day spike covering global/macro collisions, Octane checks, and the trait against our Livewire version. (4) Vendor the selected surface into an internal namespace with tests and Larastan at a strict level. (5) If any transient direct dependency is approved, record an explicit review/removal date in the dependency register. (6) Close with a removal ticket.
Maintenance. Upstream maintenance remains effectively zero and 100% transfers to us on adoption; v1.2 slightly improves the hope of upstream fixes without changing the guarantee, which is still none. Vendoring remains roughly one engineer-day plus a light annual review — but the Sortable trait raises the ongoing cost of the vendored variant, because we would own Livewire-version-specific behaviour and must re-verify it on each Livewire major. Budget that as a recurring line, not a one-off.
Support. No vendor, no SLA, no security advisories, no issue triage; escalation path is "read the source." A single 2025-era release does not constitute a support relationship and should not be represented as one in an exception request or SBOM review. Unchanged acceptability: fine only where we absorb the entire codebase into our ownership; unacceptable on a customer-facing critical path or inside an audited SBOM.
Scaling. Orthogonal to horizontal scale, with one new wrinkle: if the Sortable trait stores sort state in serialized public properties, that state rides the Livewire wire payload on every request in a sorted list. On large lists that is a real per-request cost, and it is the kind of thing that looks free in a spike and shows up in profiling later. The organizational scaling risks are unchanged and now sharper — a Livewire trait is more attractive to feature teams than a string macro, so the pressure to adopt the package will increase, and teams will adopt different subsets and drift.
Failure modes.
Sortable trait — a new failure axis introduced by v1.2.Ramp-up. Still near-zero, and v1.2 makes the trap worse: a Sortable trait is immediately legible to any Livewire developer and will spread by copy-paste from a single PR. The "own it" path costs about one engineer-day for the vendored surface, plus a half-day for license attribution, plus recurring Livewire-major verification if the trait is included. Document the decision explicitly — new joiners will otherwise infer from v1.2 that the package is maintained and safe to reach for.
Verdict: unchanged in direction. v1.2 is additive and non-breaking, introduces no deprecations, and is not a reason to reconsider adoption — but it is a reason to update the record on two points: the project is dormant-with-sporadic-activity rather than fully abandoned (continuity risk stays high, the reasoning changes), and the package now couples to Livewire, adding a second framework axis to both the compatibility matrix and the fork-maintenance budget. The zero adoption score and the 7.59 opportunity score should not be read as an endorsement. Treat this as copy-don't-depend: reject as a runtime dependency, approve selective vendoring behind an internal namespace with tests and attribution — and if the Sortable trait is the target, re-evaluate whether a bespoke sort trait is cheaper than inheriting Livewire-version-specific code from an unowned upstream.
How can I help you explore Laravel packages today?