Laravel-Backpack / CRUD

Build custom admin panels. Fast!
https://backpackforlaravel.com
MIT License
3k stars 880 forks source link

[Bug] Attribute of n-n relationship is not set during update (using select2_multiple field) #5473

Closed klaaskox closed 3 months ago

klaaskox commented 3 months ago

Bug report

What I did

I have two models: Question and Answer. These models have n-n relationships with another model named Keyvalue. These relationships have an attribute type which can be "include" or "exclude".

I am using one pivot table "keyvalue_links" with these columns:

I defined the relationship in the Question model as follows:

public function includedKeyvalues(): BelongsToMany
{
    return $this->belongsToMany(Keyvalue::class, 'keyvalue_links', 'question_id', 'keyvalue_id')
    ->wherePivot('type', '=', 'include');
}

public function excludedKeyvalues(): BelongsToMany
{
    return $this->belongsToMany(Keyvalue::class, 'keyvalue_links', 'question_id', 'keyvalue_id')
    ->wherePivot('type', '=', 'exclude');
}

I am using select2_multiple fields in my CrudController:

CRUD::field([    // Select2Multiple = n-n relationship (with pivot table)
    'label'     => "Included keyvalues",
    'type'      => 'select2_multiple',
    'name'      => 'includedKeyvalues',
    'model'     => "App\Models\Keyvalue",
    'attribute' => 'keyvalue',
    'pivot'     => true,
]);

CRUD::field([    // Select2Multiple = n-n relationship (with pivot table)
    'label'     => "Excluded keyvalues",
    'type'      => 'select2_multiple',
    'name'      => 'excludedKeyvalues',
    'model'     => "App\Models\Keyvalue",
    'attribute' => 'keyvalue',
    'pivot'     => true,
]);

What I expected to happen

When editing a question, the included and excluded keyvalues should be loaded correctly, and when updating these values, they should be stored correctly in the database.

What happened

The data is loaded correctly, but when I save/update the model, the type attribute isn't set correctly. It is always set to "include" (which is the default value).

What I've already tried to fix it

I monitored the database queries and found out that the type attribute isn't set, so the database sets it to the default value ("include")

Is it a bug in the latest version of Backpack?

After I run composer update backpack/crud the bug... is it still there? Yes

Backpack, Laravel, PHP, DB version

When I run php artisan backpack:version the output is:

### PHP VERSION:
PHP 8.1.27 (cli) (built: Dec 19 2023 20:35:55) (NTS)
Copyright (c) The PHP Group
Zend Engine v4.1.27, Copyright (c) Zend Technologies
    with Zend OPcache v8.1.27, Copyright (c), by Zend Technologies

### LARAVEL VERSION:
10.33.0.0

### BACKPACK PACKAGE VERSIONS:
backpack/basset: 1.2.2
backpack/crud: 6.3.2
backpack/devtools: 3.0.4
backpack/filemanager: 3.0.7
backpack/generators: v4.0.2
backpack/pro: 2.0.18
backpack/theme-tabler: 1.1.1
welcome[bot] commented 3 months ago

Hello there! Thanks for opening your first issue on this repo!

Just a heads-up: Here at Backpack we use Github Issues only for tracking bugs. Talk about new features is also acceptable. This helps a lot in keeping our focus on improving Backpack. If you issue is not a bug/feature, please help us out by closing the issue yourself and posting in the appropriate medium (see below). If you're not sure where it fits, it's ok, a community member will probably reply to help you with that.

Backpack communication channels:

Please keep in mind Backpack offers no official / paid support. Whatever help you receive here, on Gitter, Slack or Stackoverflow is thanks to our awesome awesome community members, who give up some of their time to help their peers. If you want to join our community, just start pitching in. We take pride in being a welcoming bunch.

Thank you!

-- Justin Case The Backpack Robot

klaaskox commented 3 months ago

Problem solved by changing the relationships:

public function includedKeyvalues(): BelongsToMany
{
    return $this->belongsToMany(Keyvalue::class, 'keyvalue_links', 'question_id', 'keyvalue_id')
    ->withPivotValue('type', 'include');
}

public function excludedKeyvalues(): BelongsToMany
{
    return $this->belongsToMany(Keyvalue::class, 'keyvalue_links', 'question_id', 'keyvalue_id')
    ->withPivotValue('type', 'exclude');
}