chelout / laravel-relationship-events

Missing relationship events for Laravel
MIT License
518 stars 33 forks source link

Events do not fire when Nova UI is used. #16

Open greggh opened 5 years ago

greggh commented 5 years ago

This package is great, does everything we need, except in Laravel Nova. When I use the Attach or Detach buttons on the Nova UI for any of my belongsToMany relationships, nothing fires, no events.

The same relationships with no code changes work great outside of Nova, and I get my events in my observer class for. In jobs running on the schedule, and even down in tinker on the command line. The events fire.

public function belongsToManyAttached($relation, Website $website, $ids)

and

public function belongsToManyDetached($relation, Website $website, $ids)

Website is the class I am observing.

chelout commented 5 years ago

I'd like to help you, but i don't have Nova license 😔

JT501 commented 5 years ago

Hi, I got the same issues when using laravel-admin which is a CMS framework similar to Nova. Although I don't have a Nova license, I want to share my experience to fix this issues in laravel-admin and hope this may help you to find out the problem in Nova.

After few hours digging in laravel-admin source code, I found out the function which update relations and in this function, there is a switch() closure as below:

.
.
.
switch (get_class($relation)) {
                case Relations\BelongsToMany::class:
                case Relations\MorphToMany::class:
                    if (isset($prepared[$name])) {
                        $relation->sync($prepared[$name]);
                    }
                    break;
                case Relations\HasOne::class:
.
.
.

The problem is get_class($relation). When using laravel-relationship-events package, it will return Chelout\RelationshipEvents\BelongsToMany instead of Relations\BelongsToMany, although Chelout\RelationshipEvents\BelongsToMany inherits Relations\BelongsToMany, it still can't match any of the cases, thus no any update (sync in my case) and event fire.

So I change the logic a little bit, and it works prefectly. And I created a pull request to laravel-admin.

.
.
.
 switch (true) {
                case $relation instanceof Relations\BelongsToMany:
                case $relation instanceof Relations\MorphToMany:
                    if (isset($prepared[$name])) {
                        $relation->sync($prepared[$name]);
                    }
                    break;
                case $relation instanceof Relations\HasOne:
.
.
.

At this moment, I don't have any idea without changing the source code of laravel-admin. If @chelout find out any workaround, it would be great ! :smile:

chelout commented 5 years ago

Thanks for share @hallelujahbaby! But without Nova code i can't fix the problem 😢 Maybe @themsaid can help with a dev license? 😬

greggh commented 5 years ago

@themsaid I'm sure you get requests all the time, but this would be amazing. None of the existing packages I can find actually fire these events when Nova is used. If @chelout had a license it could be fixed in this one. Would be a huge help.

f-liva commented 5 years ago

I see Nova using a Illuminate\Database\Eloquent\Relations\Pivot instance to do the pivot rescue. I guess that's why events don't get launched.

However, the events at the pivot update don't work that way either:

 Location::find(20993)->products()->first()->save();

Why is the event belongsToManyUpdatingExistingPivot not raised in this case?

arall commented 5 years ago

If it helps, this is what the Nova controller does when attaching a model into a morphedByMany relationship.

($pivot = $relationship->newPivot())->forceFill([
    $relationship->getForeignPivotKeyName() => $request->resourceId,
    $relationship->getRelatedPivotKeyName() => $request->input($request->relatedResource),
    $relationship->getMorphType() => $request->findModelOrFail()->{$request->viaRelationship}()->getMorphClass(),
        ]);
f-liva commented 5 years ago

Any news here?

chelout commented 5 years ago

As i can see from comments above Nova works with pivot models and doesn't support normal relations, so many-to-many relations can't be supported by this package. Ofcourse we can change basic behavior of laravel's relations, but i don't want to miss miss compatibility.

f-liva commented 5 years ago

How would you do that?

arall commented 5 years ago

Maybe we can implement an adaptor or a Nova component for doing that without messing with this repo? But I have no much clue of how to do it...

chelout commented 5 years ago

@fede91it I guess, it is possible to override laravel's methods like attach, detach, etc to use pivot models. @arall yeah, i guess we can try to write a component for Nova, but as i mentioned above i don't have license or even Nova code to do it.

arall commented 5 years ago

@chelout I might be able to provide you a license. If you're interested, could you reach me on Telegram? I'm using the same username as in here. Or email (my full name @ gmail.com).

f-liva commented 5 years ago

If necessary, I can sponsor the development of this additional feature.

chelout commented 5 years ago

@fede91it Actually i tend not to change default logic of laravel's relation system, i tend to making Nova plug-in to support our package. If you would like to sponsor this package you can always reach me on telegram @slaffka_moscow

f-liva commented 5 years ago

Why we can't create a trait for the pivot models?

arall commented 4 years ago

Any updates on this?

gavinhewitt commented 4 years ago

Came here because I was looking for the same functionality. Currently working on my Nova admin and this would solve a big issue.

chelout commented 4 years ago

There are no updates on this topic. Sorry, guys.

arall commented 4 years ago

I did a proof of concept using Laravel native Pivot models events and works fine with Nova: https://github.com/arall/laravel-relationhip-events

chelout commented 4 years ago

@arall yes, you right, it's possible with pivot events, but this package doesn't use them.

riptin commented 3 years ago

bump?

mostafaznv commented 3 years ago

This is my workaround for this issue. hope it helps.

First, you should create a model for pivot table.

namespace App\Models;

use Illuminate\Database\Eloquent\Relations\BelongsTo;
use Illuminate\Database\Eloquent\Relations\MorphPivot;

class Taggable extends MorphPivot
{
    protected $table = 'taggables';
    public $incrementing = true;
}

Then, it's time to define this model to your morph relations

namespace App\Models;

use Illuminate\Database\Eloquent\Model;
use Illuminate\Database\Eloquent\Relations\MorphToMany;

class Tag extends Model
{
    public function products(): MorphToMany
    {
        return $this->morphedByMany(Product::class, 'taggable')->using(Taggable::class);
    }
}
namespace App\Models;

use Illuminate\Database\Eloquent\Model;
use Illuminate\Database\Eloquent\Relations\MorphToMany;

class Product extends Model
{
    public function tags(): MorphToMany
    {
        return $this->morphToMany(Tag::class, 'taggable')
            ->using(Taggable::class)
            ->withTimestamps();
    }
}

now you can create an observer for your Taggable model and it works perfectly fine with nova admin panel