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

Many To Many Laravel Package

martinjuul/many-to-many

martinjuul/many-to-many is a Laravel package for simplifying many-to-many relationships. It offers convenient helpers for attaching, detaching, syncing, and managing pivot data, making related model interactions cleaner and easier to maintain.

View on GitHub
Deep Wiki
Context7

Getting Started

Because this is a low-traffic (0 stars, 0 dependents) Nova field, treat the README as the source of truth and verify the API against src/ before adopting it. The steps below are the expected shape for a Nova many-to-many field; adjust class names/path to what the package actually ships.

  1. Install into an existing Nova app

    composer require martinjuul/many-to-many
    

    Confirm the package's composer.json allows your Nova major version (Nova fields are tightly coupled to Nova 3/4/5 APIs).

  2. Look here first

    • README.md — usage snippet and any publishing/config options.
    • src/ — the field class and any ServiceProvider; check whether it registers assets, config, or macros.
    • resources/js/ (if present) — tells you whether it's a custom Vue field or a thin wrapper over Nova's BelongsToMany.
    • composer.json — require constraints against laravel/nova and php.
  3. First use case — a BelongsToMany on a resource

    use MartinJuul\ManyToMany\ManyToMany; // verify namespace from src/
    
    public function fields(NovaRequest $request): array
    {
        return [
            // ...
            ManyToMany::make('Tags', 'tags', Tag::class),
        ];
    }
    
  4. Smoke test

    • Create a record, attach 2–3 related models via the field.
    • Re-open the resource and confirm the pivot rows exist (select * from tag_post).
    • Detach and save; confirm rows are removed.

If the README examples do not run cleanly against your Nova version, stop and evaluate Nova's built-in BelongsToMany instead — the cost of debugging an unmaintained field usually exceeds the benefit.

Implementation Patterns

Standard attach/detach on a resource. Use the field in place of Nova's native BelongsToMany when you need whatever enhancement it advertises (often searchable labels, inline creation, or pivot attribute editing). Keep the relationship method standard on the model:

public function tags(): BelongsToMany
{
    return $this->belongsToMany(Tag::class)->withTimestamps();
}

Searchable / async options. For large related tables, prefer Nova's searchable mode if the field supports it:

ManyToMany::make('Tags')->searchable()

Searchable pulls options via the relationship's query; ensure the related resource is registered in NovaServiceProvider::$resources.

Pivot attributes. If the field renders pivot columns, define them on the relationship with withPivot() and, where required, withPivotValue(). Only expose pivot fields you actually validate — Nova does not enforce pivot rules for you.

Policy-aware usage. Gate attach/detach actions with related policies where possible. If the field bypasses Nova's attachAny/detachAny checks, add explicit authorization in the resource or a custom BelongsToMany subclass.

Nullable vs. required. For optional relationships use ->nullable() on the field and ->nullOnDelete() on the FK (N/A for pivot, but relevant for polymorphic variants). For required relationships, add ->rules('required', 'array') — Nova's field rules run against the submitted ID list.

Polymorphic variant. If the package ships a morph field, use it for MorphToMany relations and confirm the morph_type column is filtered correctly in the query. Test both sides of the morph map.

Compose with other Nova fields. Many-to-many is often paired with a KeyValue/Text field for pivot metadata. Keep pivot editing on the Update/Detail views only unless you've verified inline editing works in the index view.

Migration / data safety. Before swapping from the native BelongsToMany field to this one, dry-run both on the same resource. The sync behavior (sync vs syncWithoutDetaching, pivot data retention) is the most likely place for silent divergence.

Gotchas and Tips

  • Nova version lock-in. Nova's JS API changes between majors. With 0 dependents and 0 stars, there is little evidence of testing against recent Nova releases. Check composer.json require and the last commit date before adopting.
  • Asset publishing. Custom Nova fields ship compiled JS. If vendor:publish doesn't surface the assets, run npm run prod against resources/js inside the package, or inspect NovaServiceProvider for Nova::script(...)/Nova::style(...) registration.
  • Silent sync failures. Validation errors on attached IDs often surface as a generic 422. Log request()->all() in a temporary middleware if attach/detach appears to no-op.
  • Pivot columns ignored. If the field doesn't call withPivot(), pivot attribute editors render but save nothing. Mirror the withPivot list exactly between the model relation and the field configuration.
  • Order of operations on update. Nova saves fields in declaration order; a many-to-many field placed before fields that mutate the parent model can sync against a stale record. Place relationship fields last when dependencies exist.
  • Query scope leakage. If the field respects the related resource's indexQuery, global scopes can hide valid options. Test with a policy-restricted user; the option list will shrink silently.
  • Debugging. Use Nova's nova:field stubs or dump the field's resolved config via Nova::resources() and dd() on the field instance to confirm what options actually reach the front end.
  • Extension points. If the package exposes a base field class, prefer subclassing it for local overrides rather than forking — but given the project's maturity, a small local BelongsToMany wrapper may be the safer long-term choice.
  • Exit criteria. Set a clear bar for keeping the dependency: it must save/load correctly under Nova's latest release, respect policies, and pass your relationship tests. If it fails any of these and Nova's built-in field covers the need, remove it.
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.
adachsoft/changelog-linter
adachsoft/collection
payerurl/telegrambot-crypto-payment-instant-payout
dskripchenko/laravel-hybrid-search
riorizkyrainey/lara-ced
mehedimi/static-vel
zharp/zharp
nonsapiens/bigquery-model-sync
lgu-bayambang-ict-office/lgu-laravel-development-standards
andydefer/laravel-support
se7enxweb/flysystem
lampwick/laravel
jeslage/statamic-emojis
micahdshackelford/rmap-laravel
draftsmaninc/draftsman
square-bit/laravel-volition
himito/laravel-mailman
htinlynn/genius-helper
maco-studios/hephaestus
elmogy/larafast