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

Inline Index Laravel Package

ncus/inline-index

A lightweight Laravel/PHP package for working with inline indexes. Define and organize index entries directly alongside your content or models, with a simple, expressive API that drops into existing projects. Minimal setup and no heavy dependencies.

View on GitHub
Deep Wiki
Context7

Getting Started

Step 0 — settle the package identity before you type composer require. The registry blurb for ncus/inline-index reads like a schema helper ("declare database indexes inline on your Eloquent models… Artisan command to sync"), while the repository name (laravel-nova-inlineIndex) and every technical assessment describe a Nova field for inline-editing an ordering column. Those are two different packages with two different day-to-day workflows. Spend ten minutes on three files before committing:

  • composer.json — does name actually match ncus/inline-index, and what are the require constraints for laravel/framework, php, and laravel/nova?
  • src/ — is there a Laravel\Nova\Fields\Field subclass (Nova field), or a Blueprint macro / service provider registering model-level index definitions (schema helper)?
  • resources/js/ — is there a Vue component? No Vue component = not the inline-editing field.

Assume the Nova field, because the repo name and all prior assessments agree. But confirm, because installing the schema helper gives you a class no Nova resource can reference, and installing the Nova field when you needed the schema helper gives you an empty admin cell and no indexes.

If it is the Nova field (the likely case):

  1. composer require ncus/inline-index — pin the exact version in composer.json ("ncus/inline-index": "1.0.3", not ^1.0). With 7 stars and zero dependents you are the maintainer; a floating constraint is an unpinned write path in your admin.
  2. Register it like any other Nova field inside the resource's fields() method, and make the field name match the underlying column:
    use Ncus\InlineIndex\InlineIndex;
    
    public function fields(NovaRequest $request): array
    {
        return [
            Text::make('Name'),
            InlineIndex::make('Position')->sortable(),
        ];
    }
    
  3. Publish assets: php artisan nova:publish, then hard-refresh the browser. This step is the single most common source of "it doesn't work" — a stale or unpublished asset bundle renders a blank cell rather than throwing an error.
  4. Open the resource index, edit one cell, save, and confirm in the DB that only the position column changed and that the PATCH went to Nova's standard update endpoint (watch the network tab for /nova-api/...).

First use case: a curated list — featured items, pinned nav links, homepage slots — of roughly 10–50 rows, in one non-critical Nova resource, with an existing integer position/order column. Not a paginated index of thousands of rows, and not a table where the column is load-bearing for billing, permissions, or an audit trail.

If it turns out to be the schema helper instead: the day-to-day workflow is declaring indexes on the model (mirroring Blueprint syntax), then running the package's sync Artisan command in your deploy or local loop, and reviewing the generated CREATE INDEX SQL. Same caution applies — run it against a scratch database first, never blind on production.

Implementation Patterns

The column contract comes first. Before wiring the field into a resource, decide and document:

  • Column name and type (unsignedInteger('position')), nullable vs. not, and default.
  • Zero-based or one-based. Pick one and never mix.
  • Sibling scope: is position global, or per-parent ((parent_id, position))? Almost always per-parent.
  • Uniqueness: add a composite unique index in a regular migration — $table->unique(['parent_id', 'position']). This turns silent order drift into a loud database error, which is far better than discovering it in production.

Add a normalization observer. Nothing in this package re-sequences siblings. Inline edits leave gaps (1, 3, 7, 12) and, without a unique index, duplicates. Own this in your model:

protected static function booted(): void
{
    static::saved(fn (self $model) => static::normalize($model->parent_id));
    static::deleted(fn (self $model) => static::normalize($model->parent_id));
}

Run normalization in a transaction, ordered by (position, id), and re-write positions densely. Pair it with a scheduled artisan command as a safety net for rows touched outside the admin panel.

Use the field for final nudges, not bulk movement. For bulk re-sequencing, a Nova Action is the right tool: one form, one transaction, one audit entry, no per-row PATCH storm. Reserve inline editing for the last mile — "move this one up two places."

(new ActionCollection)->add(new ResequencePositions);

Expose the action only to users who could plausibly need it, and keep the inline field available underneath for single-row corrections.

Gate it. Wrap the field in a canSee closure keyed to a policy ability and a feature flag, so you can turn it off per-resource without a deploy:

InlineIndex::make('Position')
    ->canSee(fn (NovaRequest $request) =>
        config('admin.inline_index') && $request->user()->can('update', $this->resource))
    ->sortable(),

Retain a native read-only fallback. Keep Text::make('Position')->sortable()->readonly() behind the same flag. Flipping the config gives you a working screen with no editing but no blank cells — that's your rollback, and it should be documented before launch, not after an incident.

Test the write path as a feature test, not by clicking. Two tests earn their keep immediately: (a) a policy-denied user cannot mutate position via the Nova endpoint, (b) an authorized edit changes only the position column and leaves updated_at-adjacent state intact. If the package uses a bespoke endpoint instead of Nova's standard update pipeline, that first test will fail — and that's exactly the finding you want in the spike, not in production.

Scope to lenses carefully. The field works in lenses, but a lens over a large table loads a per-row input per page. Keep lens pagination small, or hide the field in large lenses.

Gotchas and Tips

Blank cells are the classic silent failure. A namespace mismatch, an unpublished asset, or a component name drift produces an empty cell — no console error, no HTTP failure. The runbook: php artisan nova:publish, hard refresh, check the network tab for a 404 on the JS chunk, confirm the component name in resources/js/ matches what the PHP field declares via component(). Write this paragraph down before operators hit it at 5pm.

Confirm the save trigger before shipping. Blur, Enter, and explicit action all behave differently. Test each: does clicking away save, does Enter save, can a fast double-edit produce two PATCHes that race? If the trigger is blur, a user tabbing through ten rows fires ten requests — acceptable for tens of rows, not for a paginated index of thousands.

Verify authorization, don't assume it. If writes go through Nova's standard update endpoint, policies and validation apply for free. If the package ships its own endpoint, you may have an authorization hole on a write path in admin. Read src/ once and know which it is. The related UX trap: a user who can't see the edit form may still see an inline editor and get a 403 — or worse, not get one.

No re-sequencing, ever. Duplicates and gaps accumulate into "stable but wrong." The unique index plus normalization observer above is not optional polish; it's the difference between a working feature and a slow data-quality incident. Cached lenses and dashboards will happily render the stale order too.

Interaction with sorting. Editing position on a table sorted by position means the row jumps out from under the cursor on refresh. That's disorienting. Decide whether to allow sorting on that column while inline editing is enabled, or default-sort by something stable (e.g. name) and let position be edited deliberately.

Pin, then test every Nova upgrade. Nova custom fields bind to Nova internals and compiled Vue assets; a Nova major bump is the primary breakage vector. Add a CI job that boots the field against the target Nova version, and budget an hour before each upgrade.

Have the fork path ready. If the package stalls, extending it is about a day's work: copy the field class into app/Nova/Fields, copy the Vue component into resources/js, fix the namespace and the build entry, done. Verify now — not during an incident — that this is actually feasible, i.e. that src/ isn't doing anything exotic and the Vue component is self-contained.

Check the license. With no visible maintainer commitment, license ambiguity surfaces at the worst possible time (audit, acquisition, security review). A one-line answer in the ticket now saves a scramble later.

Upstream support should be assumed nonexistent. Zero dependents, seven stars, no visible release cadence. Plan for "we fix it," name an owner in the ticket, and don't let upstream responsiveness appear anywhere in a timeline.

If it is the DB-index helper after all: the equivalent gotchas are that composite index column order matters ((a, b) ≠ (b, a)), unique indexes will fail on pre-existing duplicates — so dedupe before running sync — and the sync command belongs in a reviewable step of the deploy pipeline with a dry-run mode, not in a hook that silently mutates production schemas. Always read the generated SQL before it runs.

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.
3mdikram/worldmoneywords
snowsoft/config
itmosoft/laravel-subscriptions
larva/laravel-ai-qwen
diephp/sequences
users-au/socialite-provider
twidpay/twid-logger
mrnewport/laravel-plaid
mrnewport/laravel-repo
mrnewport/laravel-docsign
mrnewport/laravel-stow
mrnewport/laravel-flow
mrnewport/laravel-priceable
mrnewport/laravel-nestedterms
fredmeng/laravel-apidoc-generator
itstructure/laravel-multilingual-tools
pdustdar/elasticsearch
markupai/php-sdk
rlacerda83/lumem-microservice-shipment
uni-method/symfony-lib