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

Nova Nested Many Laravel Package

lupennat/nova-nested-many

Nova Nested Many adds a nested hasMany field to Laravel Nova, letting you create and edit related records inline within a parent form using a repeatable, sortable nested form UI, so complex one-to-many data can be managed without leaving the resource detail page.

View on GitHub
Deep Wiki
Context7

Getting Started

Install (Nova license required first). Nova resolves from nova.laravel.com, so Composer auth must be in place (auth.json locally, a CI secret) before anything installs. There is no standalone build — if Nova isn't already running in the project, stop here.

composer require lupennat/nova-nested-many

Where to look first, in order:

  1. README for the exact NestedMany::make(...) signature and whether php artisan nova:publish is required after install.
  2. vendor/lupennat/nova-nested-many/src/ — the PHP field extends Nova's HasMany and is the whole server-side surface. Read it end-to-end before merging; it's small enough to do so in one sitting.
  3. vendor/lupennat/nova-nested-many/package.json and dist/js/ — note which Nova minor the compiled Vue was built against. This is the single most common failure mode.
  4. Your child resource's fields(NovaRequest $request) — this is what actually renders inline. The child resource, not the call site, is the real configuration surface.

First use case — one relationship, scalar fields, behind a flag.

// ParentResource::fields()
NestedMany::make('Line Items', 'lineItems', LineItem::class)
    ->canSee(fn () => config('admin.nested_many'));

Then run the round trip by hand: create a parent with two child rows, edit one, delete one, and submit with a deliberate validation failure in a child to see where the error lands. Repeat as a non-super-admin in the same session — inline nested create paths frequently skip the child resource's createX policy check. Thirty minutes here tells you more than the README.

Implementation Patterns

Drive nested fields from the child resource, not the call site. The package renders whatever LineItemResource::fields() returns, so customise fields there and keep the parent resource clean. The child must be a real, registered Nova resource so fields(), rules(), and the policy resolve.

Nest by nesting the field. A second level is NestedMany inside the child resource's fields(). Two levels is what adopters have shipped; treat three as unproven until you test it yourself.

Wrap the vendor class in your own factory from day one. Every resource should call your class:

// app/Nova/Fields/NestedRelation.php
class NestedRelation extends NestedMany {}

Swapping to an in-house Vue field, or back to Nova's native two-step flow, then becomes a one-file change. This is the highest-leverage thing you do on day one.

Gate rollout with canSee() or an env flag. A config-driven canSee means you pull the field with a revert, not a deploy, and you can run it for one operator before the whole team.

Prove transactionality or add it. Nova does not wrap relationship writes in a transaction and this package issues multiple inserts per submit. Either wrap the save in DB::transaction at the action level or write a forced-failure test against the package's fill path. Don't assume atomicity.

Keep nested validation on child fields. Nested ->rules() works because the server-side field hydrates a HasMany payload. Client-side error placement is the weak spot, so test invalid submissions explicitly rather than trusting the red text lands on the right row.

Keep nested fields boring. Text, number, select, date, boolean, and a plain BelongsTo to a small lookup table all behave. File/MediaLibrary uploads, searchable BelongsTo, and computed fields inside a nested row are where Nova field packages break — add each deliberately and test in isolation.

Keep the child resource first-class. Don't hide it from the sidebar just because it now lives inline. Support staff still need it for bulk edits, exports, and audit views; both surfaces share the same model and policies, which is a feature.

Write the smoke test before the field ships. A Nova feature test walking create-with-children, update-with-children, and child-delete is the only insurance you have — and it catches a Nova upgrade within minutes instead of in production.

Gotchas and Tips

  • Version drift is the #1 failure mode. Nova 4 → 5 changed the field API and the shipped Vue component. Check package.json in the vendor directory and the build date of dist/ against your Nova minor. If they don't match, you rebuild locally — which requires the Nova source tree and a working Node toolchain. That's a real blocker, not a footnote.
  • Mixins collide. Nova field packages that patch the same Vue components (conditional fields, dependency containers, custom BelongsTo overrides) silently break each other. Audit your other field packages the first time you load the form.
  • Authorization bypass on inline creates. Log in as a non-super-admin and attempt a nested create where the child resource's createX returns false. If the row saves, stop and patch. Repeat for update and delete.
  • Nested BelongsTo gets viaResource/viaRelationship from the wrong context. Nova thinks the outer resource is the "via" and the child row is the child, so scoped queries and searchable selects behave differently than at top level. Test before relying on them.
  • Page weight is linear in child count. The field hydrates every child eagerly; 300 children is a slow form and a long transaction. Look for a ->limit()-style option in the README and treat it as a hard guardrail, not a nicety.
  • Assume unmaintained by default. 15 stars, zero dependents, one maintainer. Vendor into packages/, add a path repository to composer.json, pin the commit, and budget 1–2 engineer-days per Nova major upgrade. MIT means forking is free — fork before you depend on it, not after.
  • Debugging a blank or broken form is almost always one of: (a) child resource not registered, (b) JS asset not published or service provider not auto-discovered, (c) dist/ built against the wrong Nova minor. Check the browser console for Vue registration errors first, then nova:publish.
  • Extension points: subclass the field and override resolve/fill for payload shaping; override the child resource's fields() for conditional display of nested inputs; use ->meta() for anything the Vue side reads as a config flag. There is no plugin API — if the shipped behaviour doesn't fit, plan on editing the fork.
  • Pin package and Nova minor together in composer.lock, and keep the field behind a flag so rollout is reversible without a deploy.
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
shitoudev/permissionmanager