Я пытаюсь синхронизировать свою базу данных с внешним сервисом.
Я использую поиск по Алголии в нескольких местах в веб-приложении.
Он индексируется с помощью нескольких моделей, однако мне нужно переиндексировать его в случае внесения каких-либо изменений в базу данных, т. Е. При запуске нескольких событий модели.
Мой первый подход был к действию все в пределах ботинок метод AppServiceProvider
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();
});
}
}
Это мой подход, чтобы избежать нескольких условных выражений, используя стандартные функции модели, рассмотренные в документы.
Однако я предполагаю, что есть лучший способ использовать Laravel Event Listeners.
namespace App\Listeners;
class OrderEventListener
{
// handlers
public function subscribe($events)
{
$events->listen(
// model events
);
}
}
Хотя я не уверен, как подключиться к модельным событиям в Слушать метод.
Я настоятельно рекомендую добавить ваше собственное событие и обработчик для этой ситуации.
В вашем Product
а также Order
классы, которые вы можете переопределить boot
метод модели:
class Product extends Model
{
protected static function boot()
{
parent::boot();
self::created(function($product) {
event(new ProductCreatedEvent($product));
});
}
}
Вам нужно будет создать свой собственный ProductCreatedEvent
объект. Сейчас в EventServiceProvider
вы хотите добавить в массив listeners;
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, что повышает удобство работы ваших пользователей.
Вы можете прочитать больше об объектах события и слушателях Вот.
Альтернативным вариантом является использование модельный наблюдатель.
С некоторыми копаниями я наткнулся на событие Laravel абоненты что больше похоже на то, что я искал, поэтому я представил его как собственный ответ.
Я думаю, что это дает более сжатый код, чем наличие слушателей для каждого события.
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 отмеченным, но это, вероятно, очень актуально для людей, сталкивающихся с этим вопросом.