Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Laravel 5.8 syncing / attaching / detaching events

Laravel 5.8 is supposed to dispatch the syncing, attaching and detaching events (https://laravel.com/docs/5.8/releases search for Intermediate Table / Pivot Model Events section).

UPDATE: the release notes have been update after posting this question (more info: https://github.com/laravel/framework/issues/28050 - https://github.com/laravel/docs/pull/5096).

I tried it out but the following code throws the exception:

Call to undefined method App\ProjectUser::syncing()

NOTE: since Laravel 5.8 is supposed to dispatch the syncing event I don't want to use an external package.

class User extends Model
{
    public function projects()
    {
        return $this->belongsToMany(\App\Project::class)->using(\App\ProjectUser::class);
    }
}

class Project extends Model
{
    public function users()
    {
        return $this->belongsToMany(\App\User::class)->using(\App\ProjectUser::class);
    }
}

class ProjectUser extends Pivot
{
    public static function boot()
    {
        parent::boot();

        static::syncing(function ($item) {
            dd('syncing event has been fired!');
        });
    }
}

// web.php
$project = \App\Project::first();
$project->users()->sync([1,2]);

I tried to move the boot method from ProjectUser to User and Project but I get the same exception.

like image 523
Dan Avatar asked Mar 28 '19 07:03

Dan


2 Answers

On Laravel 5.8, when you are using the methods sync, attach or detach is going to be fired the appropriate model events (creating, updating, saving, ...) for the called action. Note that using sync, attach or detach is not going to fire any event like syncing, attaching or detaching.

More specifically, the sequence of events fired for each element passed to the sync method are:

  • saving
  • creating
  • created
  • saved

The sequence of events fired for each element passed to the attach method are:

  • saving
  • creating
  • created
  • saved

The sequence of events fired for each element passed to the detach method are:

  • deleting
  • deleted

So if you want to observe the syncing operation you actually have to observe the saving (or saved) event from the pivot model (in this case ProjectUser):

class ProjectUser extends Pivot
{
    public static function boot()
    {
        parent::boot();

        static::saving(function ($item)  {
            // this will die and dump on the first element passed to ->sync()
            dd($item);
        });
    }
}

A working example https://github.com/danielefavi/laravel-issue-example

More info on this issue https://github.com/laravel/framework/issues/28050

The release notes were misleading and they have been changed https://github.com/laravel/docs/pull/5096.

like image 112
Dan Avatar answered Oct 19 '22 19:10

Dan


If detach method called without ids (for detach all relations), events are not firing

https://github.com/laravel/framework/pull/27571#issuecomment-493451259

i tried many different way for the solve this need, but it is impossible without use external package or override many method.

I choose chelout/laravel-relationship-events package.

It's look clean and understable. And use with trait.

like image 26
eyaylagul Avatar answered Oct 19 '22 20:10

eyaylagul