Skip to content
This repository has been archived by the owner on Jul 16, 2021. It is now read-only.

[Proposal] BelongsToMany should make more use of Pivot models #953

Closed
jrbarnard opened this issue Jan 13, 2018 · 1 comment
Closed

[Proposal] BelongsToMany should make more use of Pivot models #953

jrbarnard opened this issue Jan 13, 2018 · 1 comment

Comments

@jrbarnard
Copy link

Whilst I was building an app in 5.2 a while ago I had a lot of complex relationships between models, most of which were basically belongsToMany relationships but with a lot of pivot columns where we would be querying on those a lot.

Because I wanted the pivot table to be it's own model with it's own relationships, events, helper methods etc I created a crude replacement for belongsToMany which allowed you to define the model it goes through, this was before pivot models were introduced via the ->using('\App\UserRole') method.

However with the introduction of using() all it does is hydrate a defined model class with pivot data, it doesn't define it's own logic / honour anything on the pivot model.

Basic usage

What i'd like to see is being able to define the model you are using as a pivot (a normal model, not an extension of pivot) and be able to use the features of that model when handling it via a relationship):
`
// User class
/**

  • A user has many companies via the jobs they do for them
  • A job in itself though is going to be a big table with lots of data such as start date, end date,
  • category etc. and should be queryable on it's own, as well as used as a pivot.
    */
    public function employerCompanies()
    {
    return $this->belongsToMany(
    Company::class,
    Job::class // via
    ); // Or we could still use ->using()
    }
    `
    In the above there is no need to define the intermediate table as the Job model would handle that (again less duplication).

Usage with scopes

You would then be able to deal with scopes such as the below (where withPivotScope would be a new method allowing you to define scopes you want to use on the pivot model, these scopes would be defined as normal on the Job class and therefore would be usable separately, but this way you don't need to re define wheres etc with wherePivot() or run the query on the Job model first then get the relevant companies, this would be a lot cleaner and reusable).
$user->employerCompanies()->withPivotScope([ 'complete', // Job::scopeComplete() 'oneDay' // Job::scopeOneDay() ])->get();
You would then get back all the companies that the user has done jobs for which are complete and were only a one day job.
This would also by default honour global scopes attached to the pivot model, e.g if you've got a pivot that an be soft deleted, that would work as expected, trying to get employerCompanies wouldn't return you companies where the job has been deleted (of course we would have a method to turn off pivot global scopes if needed: ::withOutThroughGlobalScopes()).

Attaching - honouring the pivot model

This would also override the attach methods etc so it uses the pivot to save the data, running model events such as Model::save(), allowing you to deal with default values (asked for in another issue), triggering events via an observer and so on

Is it useful?

What I'd like to know is if anyone would also like this functionality in core, and if so what features would people like?
I'd like to put together a scope for this feature which I can look at building if people want it, I've got a working example I can convert & alter.

It can be achieved separately and I do have an implementation that I use, but it's a bit of a forced override to get it to work as expected and existing pivot models can't be instantiated in the same way as Models currently, also it's a bit dirty to ensure joins and custom wheres still work. (This is why I'd like to have it in core because it's a bit fragile out of core).

Rough todo:

  • Alter belongsToMany relationship to accept Model as second argument instead of table
  • Allow getting pivots to hydrate normal models (not just pivot models) or allow pivot models to be instantiated, although I think we should just use Models as pivot models and they shouldn't need to be defined as such to be used a pivots (
  • Create new methods on BelongsToMany relationship to apply pivot scopes and deal with global scopes
  • Alter attach & sync methods to use the models if requested for saving and so on (may cause issues with bulk attaching but I'm not sure) so as to fire the normal model events
  • Am I missing stuff?

Cheers,
James

@jrbarnard jrbarnard changed the title BelongsToMany should make more use of Pivot models [Proposal] BelongsToMany should make more use of Pivot models Jan 13, 2018
@taylorotwell
Copy link
Member

Pivot's basically are normal models as of 5.6.

Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants