Красноречивое соединение/отсоединение/синхронизация срабатывает в любом случае?

У меня есть проект laravel, и мне нужно сделать некоторые вычисления сразу после того, как я сохраню модель и приложил к ней некоторые данные.

Есть ли какое-либо событие, которое запускается в laravel после вызова attach (или отсоединения/синхронизации)?

Ответ 1

Шаги, чтобы решить вашу проблему:

  1. Создать пользовательские отношения BelongsToMany
  2. В BelongsToMany пользовательские отношения переопределяют методы attach, detach, sync и updateExistingPivot
  3. В переопределенном методе рассылки желаемых событий.
  4. Переопределите метод ownToMany() в Model и верните свое пользовательское отношение, а не отношение по умолчанию

и что это. Я создал пакет, который уже делает это: https://github.com/fico7489/laravel-pivot

Ответ 2

Нет, в "Красноречии" нет связанных событий. Но вы можете легко сделать это самостоятельно (учитывая, например, отношение Ticket belongsToMany Component):

// Ticket model
use App\Events\Relations\Attached;
use App\Events\Relations\Detached;
use App\Events\Relations\Syncing;
// ...

public function syncComponents($ids, $detaching = true)
{
    static::$dispatcher->fire(new Syncing($this, $ids, $detaching));

    $result = $this->components()->sync($ids, $detaching);

    if ($detached = $result['detached'])
    {
        static::$dispatcher->fire(new Detached($this, $detached));
    }

    if ($attached = $result['attached'])
    {
        static::$dispatcher->fire(new Attached($this, $attached));
    }
}

объект событий прост, как это:

<?php namespace App\Events\Relations;

use Illuminate\Database\Eloquent\Model;

class Attached {

    protected $parent;
    protected $related;

    public function __construct(Model $parent, array $related)
    {
        $this->parent    = $parent;
        $this->related   = $related;
    }

    public function getParent()
    {
        return $this->parent;
    }

    public function getRelated()
    {
        return $this->related;
    }
}

то основной слушатель как разумный пример:

    // eg. AppServiceProvider::boot()
    $this->app['events']->listen('App\Events\Relations\Detached', function ($event) {
        echo PHP_EOL.'detached: '.join(',',$event->getRelated());
    });
    $this->app['events']->listen('App\Events\Relations\Attached', function ($event) {
        echo PHP_EOL.'attached: '.join(',',$event->getRelated());
    });

и использование:

$ php artisan tinker

>>> $t = Ticket::find(1);
=> <App\Models\Ticket>

>>> $t->syncComponents([1,3]);

detached: 4
attached: 1,3
=> null

Конечно, вы можете сделать это без создания объектов Event, но этот способ более удобен, гибкий и просто лучше.