Be part of JetBrains PHPverse 2026 on June 9 – a free online event bringing PHP devs worldwide together.

cwray-tech's avatar

How do I sync many to many records with multiple models using an action in Laravel Nova?

I am wanting to be able to attach/sync many different records in a many to many relationship simultaneously with a nova action. What is the best way to do this?

0 likes
5 replies
bugsysha's avatar

Just like you wrote it. Use sync or toggle or who knows what new methods Laravel has for that use case.

1 like
cwray-tech's avatar

Hey, thank you.. I guess I need a little more help than that. Is there docs anywhere on doing that? I understand how to with single items, but the main thing I am looking for is doing it with multiple items.. Through an action.

bugsysha's avatar
bugsysha
Best Answer
Level 61

Check this out https://laravel.com/docs/7.x/eloquent-relationships#updating-many-to-many-relationships

$user->roles()->sync([1, 2, 3]);

$user->roles()->syncWithoutDetaching([1, 2, 3]);

$user->roles()->toggle([1, 2, 3]);

I think this will only confuse you, but in Nova that would look something like

public function handle(ActionFields $fields, Collection $models)
{
    // only allow this action on details page (new ActionName)->onlyOnDetail()
    // cause I assume that you do not want same relationships to be applied
    // all your models
    $models->first()->roles()->sync(
        collect(array_filter($fields->getAttributes(), 'is_int'))->values()
    );
}

public function fields(): array
{
    // this bit is ugly since you want to use it through actions
    // so you have to fetch resource ID somehow
    $resourceId = request()->get('resourceId') ?? request()->get('resources');
    if (!$resourceId) {
        return [];
    }
    $model = Model::query()->find($resourceId);

    return $model->roles()
        ->pluck('text', 'id')
        ->map(function (string $text, int $id) use ($model): Element {
            return Boolean::make($id, 'role_'.$id)
                ->help(ucfirst($text))
                ->values($id, false)
                ->withMeta(['value' => collect($model->roles)->contains($id)]);
        })
        ->prepend(Heading::make('Select those that apply')) // this is only to style things better
        ->toArray();
}
cwray-tech's avatar

Thank you! I think that is what I am looking for.

Please or to participate in this conversation.