Laravel多模型事件

我正在尝试将我的数据库与外部服务同步 .

我正在Web应用程序的几个地方使用Algolia搜索 .

它是用几个模型编制索引的,但是如果对数据库进行任何更改,即在触发多个模型事件时,我需要它重新编制索引 .

我的第一个方法是在 AppServiceProviderboot 方法中执行所有操作

public function boot()
{
    $events = ['created', 'updated', 'deleted', 'restored'];

    // reindex handlers for models relevant to Algolia search
    foreach ($events as $evt) {
        Order::registerModelEvent($evt, function () {
            Order::reindex();
        });
        Product::registerModelEvent($evt, function () {
            Product::reindex();
            Product::setSettings();
        });
    }
}

这是我使用docs中示例的标准模型函数来避免多个条件的方法 .

但是我假设使用Laravel事件监听器有更好的方法 .

namespace App\Listeners;

class OrderEventListener
{
    // handlers

    public function subscribe($events)
    {
        $events->listen(
            // model events
        );
    }
}

虽然我不确定如何利用 listen 方法中的模型事件 .

回答(2)

3 years ago

我强烈建议为这种情况添加自己的事件和处理程序 .

ProductOrder 类中,您可以覆盖模型的 boot 方法:

class Product extends Model
{
    protected static function boot()
    {
        parent::boot();

        self::created(function($product) {
            event(new ProductCreatedEvent($product));
        });
    }
}

您需要创建自己的 ProductCreatedEvent 对象 . 现在在 EventServiceProvider 中你将要添加到监听器数组;

protected $listeners = [
    'App\Events\ProductCreatedEvent' => [
        'App\Listeners\UpdateAlgoliaProductIndex',
    ]
];

一旦你设置了它,你实际上可以运行 php artisan event:generate ,这将为你创建事件对象和监听器 . 我很简单,它纯粹采用了创建的产品并将其发送到 UpdateAlgoliaProductIndex 监听器 .

现在,在您的听众中,您将拥有以下内容:

class UpdateAlgoliaProductIndex
{
    public function handle($event)
    {
        Product::reindex();
        Product::setSettings();
    }
}

我建议这种方法的原因是您可以使用 ShouldQueue 接口对侦听器进行排队,这意味着您在等待应用程序重新索引Algolia时不会阻止请求,从而为您的用户带来更好的体验 .

您可以阅读有关事件对象和侦听器的更多信息here .

另一种选择是使用model observer .

3 years ago

通过一些挖掘,我遇到了Laravel事件subscribers,这更像是我所寻找的,所以我已经将它作为自己的答案提交了 .

我认为这会产生比每个事件的听众更简洁的代码 .

namespace App\Listeners;

use App\Events\OrderCreatedEvent;
use App\Events\OrderUpdatedEvent;
use Illuminate\Queue\InteractsWithQueue;
use Illuminate\Contracts\Queue\ShouldQueue;

class OrderEventListener
{
    /**
     * Handle order created events.
     *
     * @param OrderCreatedEvent $event
     */
    public function onOrderCreation(OrderCreatedEvent $event)
    {
        // do something
    }

    /**
     * Handle order updated events.
     *
     * @param OrderUpdatedEvent $event
     */
    public function onOrderUpdate(OrderUpdatedEvent $event)
    {
        // do something
    }

    /**
     * Register the listeners for the subscriber.
     *
     * @param $events
     */
    public function subscribe($events)
    {
        $events->listen(
            'App\Events\OrderCreatedEvent',
            'App\Listeners\OrderEventListener@onOrderCreation'
        );

        $events->listen(
            'App\Events\OrderUpdatedEvent',
            'App\Listeners\OrderEventListener@onOrderUpdate'
        );
    }
}

我会将marcus.ramsden的答案标记为已标记,但这可能与遇到此问题的人非常相关 .