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

Laravel Utils Laravel Package

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.

View on GitHub
Deep Wiki
Context7

Getting Started

Re-read the repository before trusting the release note. A single bullet ("Added Sortable trait") tells you almost nothing about what landed, and it changes the shape of the package: an archived, dependency-free helper collection now ships a UI-layer trait. Before installing anything:

  1. Open composer.json and check both the require and require-dev blocks for livewire/livewire. If Livewire is a hard require, installing this package for one string helper drags Livewire into a non-Livewire app. If it's absent entirely, the trait is written against Livewire's public API and will break silently on version drift — that's actually the better outcome, but only if you pin Livewire yourself.
  2. Confirm which Livewire major the trait targets. Livewire 3 renamed/removed several lifecycle hooks and changed the front-end script model; a 2023-era trait is almost certainly v2-shaped. Look for boot/initialize trait hooks, $this->emit() vs $this->dispatch(), and any wire:sort / wire:sortable Blade assumptions.
  3. Check src/ for the trait's actual surface: what methods it adds, what properties it expects you to define ($sortColumn, $sortable, etc.), and whether it registers any JS assets or expects a published view. git log/CHANGELOG on v1.2 tells you whether this was a one-commit addition.
  4. Note whether a config/ file or publishes() call arrived with v1.2. New UI features often bring new config; a config file means mergeConfigFrom and a publish step you didn't have before.

If you're already a consumer, this is a straightforward composer update — but pin it, since the tag cadence has now proven non-zero:

composer require illegal/laravel-utils:1.2.* --no-update
composer update illegal/laravel-utils --with-dependencies

First use case: build a throwaway Livewire component with a position-ordered list and apply the trait to it in php artisan tinker-adjacent fashion — i.e. in a scratch component you delete afterwards. Drag one row, assert the database order changed, and check what the trait did to your model (single update, N updates, transaction?). Do not adopt it into an existing sortable UI until you've seen that write path; if the package's idea of persistence doesn't match yours, the trait is 20 lines you can write yourself.

If you are not a Livewire shop, v1.2 changes nothing for you. The first session remains: prove the one or two helpers you actually want work on your Laravel and PHP versions, and check whether Str, Arr, Number, once(), and Collection now cover them.

Implementation Patterns

Wrap, don't sprinkle. Unchanged, and now more important: global functions and a Livewire trait in one package means app code can end up depending on it from two directions. Keep a thin app/Support/Utils.php for the helpers, and a app/Livewire/Concerns/SortsList.php trait that uses the package trait, so both replace points are single files.

Apply Sortable per component, never on a base class. The trait is the newest and least-exercised code in the package. Put it on one component, run that component's tests, then decide. If it works, re-export it through your own SortsList concern so you control the method names your views call.

Read the persistence contract before wiring the view. Whatever the trait does on drop — update per row, a bulk CASE WHEN upsert, a position swap — is now your ordering logic. If it does sequential single-row updates, wrap the whole reorder in DB::transaction() in an overridden handler; the trait almost certainly doesn't.

Override rather than modify. Traits in Livewire are resolved on the component instance, so a method defined directly on the component wins over the trait's. Redefine the sort handler on your component to add authorization ($this->authorize('reorder', $model)), logging, or a $this->dispatch('list-reordered') event, and leave the package trait untouched. This is your only clean extension point short of forking.

Fork-and-path-repository pattern. Still the right long-term integration for an unmaintained package, and now the realistic way to fix the trait for Livewire 3:

"repositories": [{ "type": "path", "url": "packages/laravel-utils" }],
"require": { "illegal/laravel-utils": "*" }

Commit the fork under packages/, bump illuminate/support and adapt the trait to your Livewire major there. Because v1.2 landed at all, "type": "vcs" against your own fork is also fine — just never depend on the upstream tag for something you've patched.

Test the trait with Livewire::test(), not browser clicks. Drag-and-drop is the easy part to get wrong and the hard part to test:

Livewire::test(TaskList::class)
    ->call('sortItem', $task->id, 3)   // use the trait's actual method name
    ->assertDispatched('list-reordered');
$this->assertSame([1,2,3,4], Task::orderBy('position')->pluck('position')->all());

The characterization test is your contract, because upstream will not tell you if the trait's behavior changes.

Fork the ordering logic when the requirements grow. Drag-sort features tend to accumulate: per-user ordering, grouped lists, optimistic UI, keyboard reordering. Any of those outgrow a one-trait helper fast. Plan the extraction: your app/Livewire/Concerns/SortsList.php becomes a hand-written implementation, and the package trait is deleted.

Migration pattern, revised. Inventory usage with a grep for the trait name (it's now a class-level dependency, so a string grep of use Sortable finds every site — easier than the helper functions). Remove trait by trait: drop the use line, paste an equivalent method onto the component, delete the dependency when the last usage is gone.

Gotchas and Tips

  • The archived-status premise no longer holds cleanly. v1.2 is a real release, so "there will be no new tags" is wrong. That is not reassuring, though: one feature commit over two years is maintenance-shaped, not maintained. Keep the tight pin, but also watch the repo for further tags — and re-read every one, because you have no track record to extrapolate risk from.
  • Livewire coupling is the new top risk. The package now reaches into Livewire's trait/lifecycle machinery, which changed materially between v2 and v3 (emit → dispatch, hook renames, script injection). A trait that works today can break on your next Livewire minor. Pin Livewire explicitly and add the sort component to your upgrade checklist.
  • Front-end requirements are invisible in composer.json. wire:sort/wire:sortable typically needs the Sortable JS plugin registered in your Livewire script config (@livewireScripts / Livewire::scripts) or Alpine import. If drag does nothing but a call() from tests works, it's JS wiring, not PHP. Check the package for a published view or asset before you debug your component.
  • Trait boot hooks run for every component that uses it. If the trait defines bootSortable(), initializeSortable(), or mountSortable(), that code executes on every request touching the component — including ones that never reorder. A missing property or a null model there is a hard failure at mount time.
  • No migration ships with it. The trait will expect a sort/position column that you add yourself. Decide the type (integer vs unsignedInteger), whether it's nullable, and whether you need a composite index like (user_id, position) before you have rows with duplicate positions.
  • Concurrency and duplicate positions. Two users reordering the same list, or a reorder racing a create, produces duplicate or skipped position values. Add a unique index if your data can tolerate it, or a periodic re-numbering job. The trait will not handle this for you.
  • N-plus-one writes. If the trait updates each affected row individually, a 200-row list is 200 queries per drop. Look for it in your query log (DB::listen in a local test) before shipping to a list that can grow.
  • Global function collisions (unchanged): root-namespace functions from autoload.files collide with your own app/Support/helpers.php and symfony/polyfill-*. Grep for name overlap.
  • Auto-discovery silently skipping (unchanged): check php artisan package:discover -v and bootstrap/cache/packages.php. Note that a trait doesn't need discovery — it's class-autoloaded — so a "the trait works but the helpers don't" symptom points straight at discovery, not the package.
  • Config publishing is one-way: publish once, commit, stop re-publishing. New features in v1.2 may have added keys your published config lacks; diff vendor/.../config against your copy after the update rather than blindly re-publishing.
  • Behavioral edge cases to re-test: reordering to the same position (should be a no-op, not a write), reordering to position 0 or past the end, single-item lists, and empty lists. These are exactly the boundaries a fresh 20-line trait gets wrong.
  • Prefer native equivalents where they exist. Still true for the helper half of the package: Str::of(), Arr::get(), Number::format(), once(), throw_if()/throw_unless(), rescue(). If v1.2's trait is the only thing you want, extract the 20–30 lines and drop the dependency; you'll be ahead on both Livewire-version agility and upgrade review.
  • Opportunity, not risk-free adoption. v1.2 slightly improves the outlook — someone is still watching the repo — but a single Livewire helper doesn't fix the illuminate/support constraint, the absence of a security path, or the zero-dependents debugging tax. The play is unchanged: vendor it, add tests for both the helpers and the sort behavior, bump constraints in your fork, and tag your own release. Treat v1.2 as a starting point to fork from, not as evidence the upstream is now supported.
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.
uni-method/symfony-lib
tacticmedia/scim-server-bundle
neika-ai/symfony-bundle
mattleads/agent-publishing-bundle
glavweb/framework-bundle
glavweb/extra-bundle
glavweb/api-bundle
glavweb/admin-bundle
adachsoft/api-version-bundle
elsayed85/laravel-api-exceptions
ouhssini/laravel-demo-mode
daworks/ncloud-outbound-mailer-driver
gp247/cms
ignibyte/aic-gates
nexa-merchant/blog
novasa/laravel-language-center
opencage/geocode
adolfoholzer/parameters
livenetworks/ln-starter
cgv/localized-resource