Laravel-Backpack / CRUD

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

[Bug] Repeatable field with belongsToMany relationship not saving data #5629

Closed GregaUNK closed 2 months ago

GregaUNK commented 2 months ago

Bug report

Iam using Repeatable field with relationship belongsToMany.

Below is my working field for update operation. It works on version 6.7.16. After this version I get error:

Backpack\CRUD\app\Library\CrudPanel\CrudPanel::setLocaleOnModel(): Argument #1 ($model) must be of type Illuminate\Database\Eloquent\Model, stdClass given, called in /Development/myappvendor/backpack/crud/src/app/Library/CrudPanel/Traits/Update.php on line 129

Saving this repeatable fields thru belongsToMany works only till version 6.7.15. It shows now error, it just doesn't save anything.

$this->crud->entry->products = json_decode($this->crud->getCurrentEntry()->products->map(function ($product) {
                return [
                    'product_id' => $product->id,
                    'quantity' => $product->pivot->quantity,
                    'price' => $product->pivot->price
                ];
            })->toJson());

  $this->crud->addField([
            'name' => 'products',
            'label' => 'Products',
            'type' => 'repeatable',
            'tab' => 'Order',
            'fields' => [
                [
                    'name' => 'product_id',
                    'type' => 'select2_from_ajax',
                    'label' => 'Products',
                    'model' => "App\Models\Product", // replace with path to Product model
                    'attribute' => 'full_name', // attribute on Product model that is shown to user
                    'data_source' => url('/api/product/getSearchProducts'),
                    'method' => 'post',
                    'wrapper' => ['class' => 'form-group col-md-6'],
                ],
                [
                    'name' => 'quantity',
                    'type' => 'number',
                    'label' => 'Quantity',
                    'attributes' => ["step" => "0.01"], // Set step for quantity
                    'wrapper' => ['class' => 'form-group col-md-3'],
                ]
            ],
            //      'disabled' => 'disabled',
            'new_item_label' => 'Dodaj produkt', // Label for the button to add a new product entry
            'init_rows' => 0, // Number of rows when first loading the page
            'value' => isset($jobOrder->products) ? $jobOrder->products->map(
                function ($product) {
                    return [
                        'product_id' => $product->id,
                        'quantity' => $product->pivot->quantity, // Assuming pivot table has quantity field
                    ];
                }
            ) : null
        ]);

Thats my relationship:

public function products()
    {
        return $this->belongsToMany(Product::class, 'job_order_products')
            ->withPivot('quantity', 'price')
            ->withTimestamps();
    }

Is it a bug in the latest version of Backpack?

Yes. The last version that works is 6.7.16.

Backpack, Laravel, PHP, DB version

PHP VERSION:

8.3.7

PHP EXTENSIONS:

Core, date, libxml, openssl, pcre, sqlite3, zlib, bcmath, bz2, calendar, ctype, curl, dba, dom, hash, FFI, fileinfo, filter, ftp, gd, gettext, gmp, json, iconv, intl, SPL, ldap, mbstring, session, standard, odbc, pcntl, exif, mysqlnd, PDO, pdo_dblib, pdo_mysql, PDO_ODBC, pdo_pgsql, pdo_sqlite, pgsql, Phar, posix, pspell, random, readline, Reflection, mysqli, shmop, SimpleXML, soap, sockets, sodium, sysvmsg, sysvsem, sysvshm, tidy, tokenizer, xml, xmlreader, xmlwriter, xsl, zip, Zend OPcache

LARAVEL VERSION:

10.48.20.0

BACKPACK PACKAGE VERSIONS:

backpack/basset: 1.3.5 backpack/crud: 6.7.16 backpack/generators: v4.0.5 backpack/logmanager: v5.0.2 backpack/permissionmanager: 7.2.1 backpack/pro: 2.1.7 backpack/revise-operation: 2.0.0 backpack/theme-coreuiv2: 1.2.5 backpack/theme-coreuiv4: 1.1.2 backpack/theme-tabler: 1.2.11

karandatwani92 commented 2 months ago

Hey @GregaUNK

You should use the relationship field for this use case. This way, you will not have to fetch or save data manually — no JSON conversion is required.

GregaUNK commented 2 months ago

Thanks a lot! 💯 👍

I had already tried this method before, but I encountered an issue where my browser tab froze due to the huge number of products. I initially attempted to use a select2_from_ajax field for products within subfields, which I now understand was incorrect. :)

You should use pivotSelect for that purpose.

Now, everything works perfectly, except for the “allow_duplicate_pivots” feature. I have already commented on this issue here: #5538.

I’m not sure whether I should close this ticket or not. I realize now that my implementation was incorrect, but it was working well before the mentioned update.

Let’s leave that decision to someone else. :)

pxpm commented 2 months ago

Hey @GregaUNK thanks for the feedback, very happy we were able to find and fix your issue 🥳 Another thing we introduced recently that helps a lot when loading a bunch of relations in the update form, is the eagerLoadRelationships https://backpackforlaravel.com/docs/6.x/crud-operation-update#how-to-use-1 (see step 3)

If you did everything as stated in the docs: https://backpackforlaravel.com/docs/6.x/crud-fields#allow-user-to-select-multiple-times-the-same-pivot and you are still experiencing issues, please an issue providing us the pivot model, the field definition etc so that we can reproduce it 🙏 you know the drill 👍

I will be closing this one in the meanwhile.

Cheers