【问题标题】:Laravel Multiple Model EventsLaravel 多模型事件
【发布时间】:2016-10-03 09:11:44
【问题描述】:

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

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

它被几个模型索引,但是我需要它来重新索引,以防对数据库进行任何更改,即当多个模型事件被触发时。

我的第一个方法是在 AppServiceProvider

的 boot 方法中执行所有操作
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 方法中利用模型事件。

【问题讨论】:

    标签: php laravel laravel-5 laravel-5.2 algolia


    【解决方案1】:

    我强烈建议针对这种情况添加您自己的事件和处理程序。

    在您的 Product 和 Order 类中,您可以覆盖模型的 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。

    【讨论】:

    • 我已经为通知做了这种事情,例如产品更新了ProductCreatedEvent 被解雇。我对此没问题,因为我只需要在您展示的引导方法中使用self::updated() 触发它。但是,每当触发任何模型事件时,都应该执行此处的重新索引之类的操作,并且我正在寻找一种不需要列出每个模型事件以及后续事件侦听器、处理程序等的解决方案。更多地研究它会不会更好创建一个工作并在启动时调度它?然后它仍然可以实现 ShouldQueue 但它总是会触发。
    • 如果你想要每一个模特活动,如果你关注saved而不是created,你可能会更幸运。 ShouldQueue 消除了定义额外的 Job 对象的需要。如果您不想立即运行它,我建议您在产品对象中添加一个requires_search_indexing 字段。然后,您可以让 cron 作业定期进行扫描,以便对更新进行分组。
    • 这很好。如果您想要一些中间立场,我接受它,您仍然主张使用所有事件侦听器。 Laravel 5.2 似乎已经从文档中删除了模型观察者,这让我想知道他们是否不再推荐这种方法。
    • 是的,我确实想知道模型观察者是否正在被放弃,而只是为了引发更具体的领域事件而不是直接挂钩到 Eloquent 事件。如果这是一个问题,它确实会让你与 Eloquent 脱钩。
    【解决方案2】:

    通过一些挖掘,我遇到了 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 的答案保留为标记,但这可能与遇到此问题的人非常相关。

    【讨论】:

      猜你喜欢
      • 2015-10-20
      • 1970-01-01
      • 2015-10-25
      • 1970-01-01
      • 1970-01-01
      • 2013-10-28
      • 1970-01-01
      • 1970-01-01
      • 2021-09-19
      相关资源
      最近更新 更多