Crud: [Bug] Relationship field broken - underscore in field name

Created on 26 May 2020  路  13Comments  路  Source: Laravel-Backpack/CRUD

Bug report

Relationship field seems broken if you have an underscore in the name of the field.

What I did

$this->crud->addFields([
    [
        'label' => 'Billing address',
        'type' => "relationship",
        'name' => 'billing_address',
        'attribute' => 'full_address',
        'ajax' => true,
        'inline_create' => [ 
            'entity' => 'address',
            'force_select' => true,
            'modal_class' => 'modal-dialog modal-xl',
        ]
    ],
]);

What I expected to happen

A good route generated : /site/fetch/billing_address

What happened

A bad route has been generated : /site/fetch/billing-address

Backpack, Laravel, PHP, DB version

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

PHP VERSION:

PHP 7.2.19 (cli) (built: May 29 2019 13:58:59) ( ZTS MSVC15 (Visual C++ 2017) x64 )
Copyright (c) 1997-2018 The PHP Group
Zend Engine v3.2.0, Copyright (c) 1998-2018 Zend Technologies

LARAVEL VERSION:

v7.10.3@6e927e78aafd578d59c99608e7f0e23a5f7bfc5a

BACKPACK VERSION:

4.1.3@02988a0d14b09e55949781d729060df910f0d94b

Bug

Most helpful comment

Ok, managed to get it working this way : (still don't know why it works this way)

[
                'label' => 'Adresse',
                'type' => "relationship",
                'name' => 'address_id',
                'entity' => 'address',
                'attribute' => 'full_address',
                'ajax' => true,
                'placeholder' => "Choisissez une adresse",
                'inline_create' => true
            ],
            [
                'label' => 'Adresse de facturation',
                'type' => "relationship",
                'name' => 'billing_address_id',
                'entity' => 'address',
                'data_source' => url($this->crud->route.'/fetch/billing-address'),
                'attribute' => 'full_address',
                'ajax' => true,
                'placeholder' => "Choisissez une adresse",
                'inline_create' => true
            ],

All 13 comments

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:

  • Bug Reports, Feature Requests - Github Issues (here);
  • Quick help (_How do I do X_) - Gitter Chatroom;
  • Long questions (_I have done X and Y and it won't do Z wtf_) - Stackoverflow, using the backpack-for-laravel tag;
  • Showing off something you've made, asking for opinion on Backpack/Laravel matters - Reddit;

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

In method setupFetchOperationRoutes of FetchOperation, I can see :

protected function setupFetchOperationRoutes($segment, $routeName, $controller)
    {
        // get all method names on the current model that start with "fetch" (ex: fetchCategory)
        // if a method that looks like that is present, it means we need to add the routes that fetch that entity
        preg_match_all('/(?<=^|;)fetch([^;]+?)(;|$)/', implode(';', get_class_methods($this)), $matches);

        if (count($matches[1])) {
            foreach ($matches[1] as $methodName) {
                Route::post($segment.'/fetch/'.Str::kebab($methodName), [
                    'uses'      => $controller.'@fetch'.$methodName,
                    'operation' => 'FetchOperation',
                ]);
            }
        }
    }

I thought problem could be in the field template, so I had a look at relationship/fetch.blade.php :

$routeEntity = Str::kebab($entityWithoutAttribute);

and

$field['data_source'] = $field['data_source'] ?? url($crud->route.'/fetch/'.$routeEntity);

It seems OK. The truth is elsewhere?

@tabacitu @pxpm does this ring a bell to you ?

Hello @dividy, thanks for report.

What's your fetch function definition ?

Best,

protected function fetchBillingAddress()
    {
        return $this->fetch([
            'model' => \App\Models\Address::class,
            'searchable_attributes' => ['name'],
            'paginate' => 10,
        ]);
    }

If I add this parameter to the relationship field, it works:

'data_source' => url($this->crud->route.'/fetch/billing-address'),

I also, there is something strange when updating.

It tried to update the field "address", instead of "address_id" and the request validation doesn't work either...

Ok, managed to get it working this way : (still don't know why it works this way)

[
                'label' => 'Adresse',
                'type' => "relationship",
                'name' => 'address_id',
                'entity' => 'address',
                'attribute' => 'full_address',
                'ajax' => true,
                'placeholder' => "Choisissez une adresse",
                'inline_create' => true
            ],
            [
                'label' => 'Adresse de facturation',
                'type' => "relationship",
                'name' => 'billing_address_id',
                'entity' => 'address',
                'data_source' => url($this->crud->route.'/fetch/billing-address'),
                'attribute' => 'full_address',
                'ajax' => true,
                'placeholder' => "Choisissez une adresse",
                'inline_create' => true
            ],

I also, there is something strange when updating.

It tried to update the field "address", instead of "address_id" and the request validation doesn't work either...

This is expected behaviour, and I think it's in docs. If you use relationship, you validate also with relationship name, in your scenario would validate address => 'required'

I will have a look and investigate if we really need to Str::kebab here.

Once again, thank you @dividy ! \o

Yes, thanks.

However, I still have a bug...

When I create an item.

I don't select an Address, however I select a Billing Address.
Backpack saves the Billing Address in both fields instead of saving NULL in Address field. (Update works fine tho).

I thought I had to change the 'entity' property, which is 'address' for both to 'address' and 'billing_address' respectively, but then I get this error : Route [billing_address-inline-create-save] not defined.

Do you have an idea ? ;-)

Any clue @pxpm ?

Ok @pxpm ,

Managed to fix it by replacing Str::kebab with Str::snake
(Str::kebab replaces underscores by hyphens)

Fixed by #2905 so let's move the conversation there please. Thanks a lot for raising the issue @dividy ! Very good collaboration between you and @pxpm here I see.

Was this page helpful?
0 / 5 - 0 ratings

Related issues

sokvebolkol picture sokvebolkol  路  3Comments

sseggio picture sseggio  路  3Comments

sonoftheweb picture sonoftheweb  路  3Comments

lotarbo picture lotarbo  路  3Comments

jorgepires picture jorgepires  路  3Comments