Laravel 5.8 синхронизация/присоединение/отключение событий

Laravel 5.8 должен отправлять события синхронизации, присоединения и отсоединения (https://laravel.com/docs/5.8/releases найдите раздел Промежуточная таблица/события сводной модели).

ОБНОВЛЕНИЕ: примечания к выпуску были обновлены после публикации этого вопроса (дополнительная информация: https://github.com/laravel/framework/issues/28050 - https://github.com/laravel/docs/pull/5096).

Я попробовал это, но следующий код выдает исключение:

Вызов неопределенного метода App\ProjectUser::syncing()

ПРИМЕЧАНИЕ: поскольку Laravel 5.8 должен отправлять событие синхронизации, я не хочу использовать внешний пакет.

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]);

Я попытался переместить метод загрузки с ProjectUser на User и Project, но получаю то же исключение.


person Dan    schedule 28.03.2019    source источник
comment
У вас есть только boot() метод.   -  person Tpojka    schedule 28.03.2019
comment
@Tpojka, можно поконкретнее, пожалуйста? Это распространенный способ сказать laravel прослушать событие (другой способ — создать наблюдателя).   -  person Dan    schedule 28.03.2019
comment
Извините, не использовал это таким образом. Я честно использую наблюдателей, но не использовал сквозной метод загрузки. Я только что искал документы, и нет никакого метода синхронизации.   -  person Tpojka    schedule 28.03.2019


Ответы (2)


В Laravel 5.8, когда вы используете методы sync, attach или detach, будут запущены соответствующие события модели (создание, обновление, сохранение,...) для вызываемого действия. Обратите внимание, что использование sync, attach или detach не вызовет никаких событий, таких как синхронизация, присоединение или отключение.

В частности, последовательность событий, запускаемых для каждого элемента, переданного методу sync, следующая:

  • сохранение
  • создание
  • созданный
  • сохранен

Последовательность событий, запускаемых для каждого элемента, переданного методу attach:

  • сохранение
  • создание
  • созданный
  • сохранен

Последовательность событий, запускаемых для каждого элемента, переданного методу detach:

  • удаление
  • удален

Поэтому, если вы хотите наблюдать за операцией синхронизации, вам действительно нужно наблюдать за событием сохранения (или сохранения) из сводной модели (в данном случае 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);
        });
    }
}

Рабочий пример https://github.com/danielefavi/laravel-issue-example

Дополнительная информация по этой проблеме https://github.com/laravel/framework/issues/28050

Примечания к выпуску вводили в заблуждение и были изменены https://github.com/laravel/docs/pull/5096.

person Dan    schedule 29.03.2019

Если метод отсоединения вызывается без идентификаторов (для отсоединения всех отношений), события не срабатывают

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

Я пробовал много разных способов решить эту проблему, но это невозможно без использования внешнего пакета или переопределения многих методов.

Я выбираю пакет chelout/laravel-relationship-events.

Это выглядит чистым и понятным. И использовать с чертой.

person eyaylagul    schedule 10.07.2019
comment
Да, вы правы, для метода отсоединения требуются идентификаторы, если вы хотите запускать события. Решение для отделения всех элементов и событий также может быть: $project->users()->detach( User::all()->pluck('id') ); - person Dan; 10.07.2019