LeanAdmin / feature-discussions

The place for discussing new features
6 stars 0 forks source link

BelongsToMany Relation #31

Open ssmusoke opened 3 years ago

ssmusoke commented 3 years ago

While the documentation is very clear that this is not in scope, I thought that it would still be great to open up a discussion here on the feature.

I coming from Nova and the way it was simplified was that the BelongsToMany is only available after a resource has been created/edited and you can only work on the pivot table relationship

IMO this would simplify the implementation

Thoughts and comments are welcome

stancl commented 3 years ago

If you want native BelongsToMany support it'd help me a lot if you could share your exact uses of the relation.

The thing about BelongsToMany is that it can represent vastly different things (and the UI for each of those things would be very unique), so I want to have an idea about what people are commonly using it for.

ssmusoke commented 3 years ago

Here are screenshots from how I have used it before in Nova adding roles and permissions for a user - all the UI provides is adding the pivot-table relationship, possibly if additional fields are provided there may be a model to edit and create

User_Details

stancl commented 3 years ago

I see. I can think of the following use cases:

ssmusoke commented 3 years ago

And I see them in two major categories

robertorinaldi-dev commented 3 years ago

A feature which could be useful sometimes is the possibility to set a limit to the number of related resources. If the limit is reached, the add button became disabled. I don't know if I'm the only one who ever needed something like this.

stancl commented 3 years ago

@roberto-mgquadro What was the use case for that? Can you give an example?

I can imagine this working with HasMany too.

robertorinaldi-dev commented 3 years ago

The last time I needed this feature was for creating padel teams. Each team could have a maximum of 2 players (1 in case the teammate has not yet been found). Same thing for the creation of the matches, each of which could have a maximum of two challengers.

stancl commented 3 years ago

Ah yeah that makes sense. Does Laravel let you do $this->belongsToMany(Foo::class)->limit(2)?

And if so, does it enforce it on both reads and writes or only reads? 🤔

robertorinaldi-dev commented 3 years ago

As far as I know, no. For this reason, a limit at a higher level may be useful

robertorinaldi-dev commented 3 years ago

I know that I could have created the two players directly on the team, but it was inconvenient for me due to other features. Furthermore, this example can be adapted to cases where the maximum is not only 2 but maybe 4 or 10.

stancl commented 3 years ago

That's a good suggestion. I guess I can add ->limit() and make it read from the relation by default.

ssmusoke commented 3 years ago

Additional use cases

MikeCraig418 commented 3 years ago

One thing that is difficult to configure with HasMany/BelongsToMany in Nova are the pivot fields.

Any relational component here would be improved greatly if Pivot tables / custom fields on the pivot model can be accessed and edited.

stancl commented 3 years ago

@949mac Can you describe exactly what pains you had with it in Nova? I don't think I've used it.

molcsab commented 2 years ago

This is my use case for BelongsToMany:

Simplified table structure:

contracts
    id - integer
    contract_number - string

machines
    id - integer
    name - string

contract_machine
    id - integer
    contract_id - integer
    machine_id - integer
    serial_number - string
    manufacture_year - year

My models and resources in Nova:

// Contract Model
class Contract extends Model
{
public function machines()
    {
        return $this->belongsToMany(Machine::class)
        ->withPivot(['id','serial_number','manufacture_year']);
    }
}

// Machine Model
class Machine extends Model
{
public function contracts()
    {
        return $this->belongsToMany(Contract::class)
            ->withPivot(['serial_number','manufacture_year']);
    }
}

// Contract Resource (Nova)
class Contract extends Resource
{
    public function fields(Request $request)
    {
        return [
            ID::make('ID', 'id')->sortable(),
            BelongsToMany::make('Machines', 'machines', Machine::class)
                ->fields(function () {
                    return [
                        Text::make('Serial Number','serial_number'),
                        Text::make('Manufacture Year','manufacture_year'),
                    ];
                })
                ->allowDuplicateRelations()
                ->searchable(),
        ];
    }
}

// Machine Resource (Nova)
class Machine extends Resource
{
    public function fields(Request $request)
    {
        return [
            ID::make('ID', 'id')->sortable(),
            BelongsToMany::make('Contracts','contracts',Contract::class)
            ->fields(function () {
                return [
                    Text::make('Serial Number','serial_number'),
                    Text::make('Manufacture Year','manufacture_year'),
                ];
            }),
        ];
    }
}    

I'll have to be able to attach and dispaly exisitng machines to a contract with additional fields in the pivot table

Contract_Details

I am in the process to rewrite the application with Lean and the BelongsToMany relation would come very handy, or or some workaround.