Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Fire events/allow observers on pivot models #4022

Closed
jfexyz opened this issue Apr 1, 2014 · 9 comments
Closed

Fire events/allow observers on pivot models #4022

jfexyz opened this issue Apr 1, 2014 · 9 comments

Comments

@jfexyz
Copy link
Contributor

jfexyz commented Apr 1, 2014

For pivot models, model events are not fired, nor can you register observables. I'm primarily talking about any relationship that requires a pivot table, and therefore extends Pivot. There was a previous pull request, but I don't believe the workaround there will work for pivots.

If events are fired, we'd also need to be able to register observers against pivots, but that's not currently possible because Pivots can't be instantiated by themselves. (In my case, I'd like to track which user updates a model (including pivots). Am I missing something, or could Illuminate\Database\Eloquent\Model::getObservableEvents() be a static method, thereby avoiding the second issue?

@taylorotwell
Copy link
Member

I think what you could do is extend the Pivot class by override the newPivot method on a base model class. Then return your extended pivot.

@jfexyz
Copy link
Contributor Author

jfexyz commented Apr 4, 2014

Unfortunately, your answer doesn't apply to the second part of this issue. (I do understand how to use newPivot to set up custom pivot models; I've got that working just fine.)

Sorry, I was wrong about the first part of this issue. Model events are fired for pivot models. Not sure why I didn't notice that. I'll blame it on the fact that I originally wrote this issue about using Observables with Pivots (as I'm trying to implement the culpa package), and then for some reason got it in my head that events weren't being fired at all.

However, it is not possible to register model observers for pivot models, because calling CustomPivot::observe requires instantiating the model, and the Pivot class has a different constructor signature:

Argument 1 passed to Illuminate\Database\Eloquent\Relations\Pivot::__construct() must be an instance of Illuminate\Database\Eloquent\Model, none given, called in /var/www/supergrooper/vendor/laravel/framework/src/Illuminate/Database/Eloquent/Model.php on line 303 and defined

As far as I can tell, it all basically comes down to the fact that Model::getObservableEvents must be called on an instance, when it seems quite likely that it could be a static method. (Is Model::$observables ever going to change per-instance, or just per-class?)

@jfexyz
Copy link
Contributor Author

jfexyz commented Apr 4, 2014

Also, I have no need for it myself right now, but it seems like you couldn't call CustomPivot::flushEventListeners for the same reason: it instantiates the model in order to call Model::getObservableEvents.

@moleculezz
Copy link

@joshuajabbour How did you get events to fire for pivot model?
I have tried to set this up, but haven't succeeded.
http://laravel.io/bin/qLD06

@sgelbart
Copy link

I'd like an example too.

@sgelbart
Copy link

@moleculezz the code you pasted doesn't show up anymore? I think it's an issue with laravel.io.

Basically, if you're updating the pivot model directly events should fire for it but as Pivot (so you'd have to check and see which table was actually modified). I wasn't testing this with a class extending pivot (i.e., I don't have an actual class specifically for Membership) but I was able to register the 'saving' event using the following code I registered in my start.php:

Event::listen('eloquent.saving: Illuminate\Database\Eloquent\Relations\Pivot', function($contact){
    ...
});

I triggered this in my code using my weird round-about way for updating a pivot table:

$member = $this->members()->where('user_id',$user_id)->first();
$member->pivot->update(array('is_admin'=>1));

(since then I've actually found $this->members()->updateExistingPivot($user_id,array('is_admin'=>1) which doesn't fire the event beacuse it doesn't actually access the pivot class)

I believe that if I were to actually create a membership class that extended the pivot all events would fire and I think you could even register them like Event::listen('eloquent.saving: Membership, function($contact){.. (will test if I have time):

I actually don't want to have to create individual classes for my belongsToMany relationships though, and I think this is possible to trigger relationships with a bit of work in the belongsToMany class, which would mean you don't HAVE to create classes for your pivots to get events to fire. How about triggering events in the following format: 'eloquent.added: Group.members' (for adding, added, deleting, deleted, updating, updated)

I'm working on doing a drilldown in my code with the events but wanted to put it out there to see if anyone had any comments/suggestions and to post my findings so far.

As an additional note, these event names won't actually work with models that extend Pivot (I guess they could but I'm not sure how to get the relationship that connects the pivot to the parent from within the Pivot class?) so this is kinda vering off the exact title of this post...

@moiroca
Copy link

moiroca commented Aug 27, 2015

Is this being handled already? Thank you guys. I have a project that badly needs this feature.

@sgelbart
Copy link

@moiroca - I just don't use pivots...
Instead of doing $user->groups
I do $user->memberships (then in foreach I do $membership->group)
then I do Membership::create(['user_id'=>$userId, 'group_id'=>$groupId]);
(Membership extends from Eloquent not pivot)
You can still keep the $user->groups relationship for easy access, I just don't use ->attach or anything
(I have a library I created for firing events I can send you as well but I highly recommend the above method...will save you tons of headache..)

@fico7489
Copy link

fico7489 commented Nov 1, 2017

take a look at my package : https://github.com/fico7489/LaravelPivot

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

No branches or pull requests

6 participants