我想为一些事件实现电子邮件通知。此外,我还使用Laravel数据库队列异步处理了这些事件
这是我所拥有的:
事件类别:
<?php
namespace AppEvents;
use AppModelsServerReviewVote;
use IlluminateBroadcastingInteractsWithSockets;
use IlluminateFoundationEventsDispatchable;
use IlluminateQueueSerializesModels;
class NewServerReviewVote
{
use Dispatchable, InteractsWithSockets, SerializesModels;
/**
* Create a new event instance.
*
* @return void
*/
public function __construct(public ServerReviewVote $serverReviewVote)
{
}
}
侦听器类:
<?php
namespace AppListeners;
use AppEventsNewServerReviewVote;
use AppNotificationsNewServerReviewVote as NewServerReviewVoteNotification;
use IlluminateContractsQueueShouldQueue;
class SendNewServerReviewVoteNotification implements ShouldQueue
{
/**
* Handle the event.
*
* @param NewServerReviewVote $event
* @return void
*/
public function handle(NewServerReviewVote $event)
{
$event->serverReviewVote->serverReview->author
->notify(new NewServerReviewVoteNotification($event->serverReviewVote->serverReview));
}
}
通知类别:
<?php
namespace AppNotifications;
use AppModelsServerReview;
use AppModelsUser;
use IlluminateBusQueueable;
use IlluminateContractsQueueShouldQueue;
use IlluminateNotificationsMessagesMailMessage;
use IlluminateNotificationsNotification;
class NewServerReviewVote extends Notification implements ShouldQueue
{
use Queueable;
/**
* Create a new notification instance.
*
* @return void
*/
public function __construct(private ServerReview $serverReview)
{
}
/**
* Get the notification's delivery channels.
*
* @param User $notifiable
* @return array
*/
public function via(User $notifiable): array
{
return ['mail'];
}
/**
* Get the mail representation of the notification.
*
* @param User $notifiable
* @return IlluminateNotificationsMessagesMailMessage
*/
public function toMail(User $notifiable): MailMessage
{
return (new MailMessage)
->subject('New vote for your review!')
->greeting("Hello, {$notifiable->name}!")
->line("We got a new vote for your review for {$this->serverReview->server->name} server!")
->line("Your review currently have {$this->serverReview->votesUpCount()} upvotes and {$this->serverReview->votesDownCount()} downvotes.")
->line("Click the button below to navigate to the server page:")
->action($this->serverReview->server->name, route('servers.show', ['server' => $this->serverReview->server->slug]));
}
}
我正在从这个观察员那里发射事件:
<?php
namespace AppObservers;
use AppEventsNewServerReviewVote;
use AppModelsServerReviewVote;
class ServerReviewVoteObserver
{
/**
* @param ServerReviewVote $serverReviewVote
*/
public static function created(ServerReviewVote $serverReviewVote)
{
event(new NewServerReviewVote($serverReviewVote));
}
}
我配置了队列数据库驱动程序,我的数据库有jobs
表。我的期望是这个事件将被添加到这个表中,然后我可以使用php artisan queue:work
来处理它。但由于某些原因,电子邮件是同步发送的,而不是添加到队列中。我错过了什么?
好吧,我一直在尝试不同的方法,并找到了如何将侦听器添加到队列中。我将public $connection = 'database'
属性添加到侦听器类中。以下是它现在的样子:
<?php
namespace AppListeners;
use AppEventsNewServerReviewVote;
use AppNotificationsNewServerReviewVote as NewServerReviewVoteNotification;
use IlluminateContractsQueueShouldQueue;
class SendNewServerReviewVoteNotification implements ShouldQueue
{
/**
* Connection for queue
* @var string
*/
public string $connection = 'database';
/**
* Handle the event.
*
* @param NewServerReviewVote $event
* @return void
*/
public function handle(NewServerReviewVote $event)
{
$event->serverReviewVote->serverReview->author
->notify(new NewServerReviewVoteNotification($event->serverReviewVote->serverReview));
}
}
据我从Laravel文档中了解,这个属性不是必需的,但由于某种原因,监听器在没有它的情况下无法调度到队列。现在它工作得很好!
我还清除了通知类,因为它不需要实现ShouldQueue
接口和使用Queueable
特性。以下是它现在的样子:
<?php
namespace AppNotifications;
use AppModelsServerReview;
use AppModelsUser;
use IlluminateNotificationsMessagesMailMessage;
use IlluminateNotificationsNotification;
class NewServerReviewVote extends Notification
{
/**
* Create a new notification instance.
*
* @return void
*/
public function __construct(private ServerReview $serverReview)
{
}
/**
* Get the notification's delivery channels.
*
* @param User $notifiable
* @return array
*/
public function via(User $notifiable): array
{
return ['mail'];
}
/**
* Get the mail representation of the notification.
*
* @param User $notifiable
* @return IlluminateNotificationsMessagesMailMessage
*/
public function toMail(User $notifiable): MailMessage
{
return (new MailMessage)
->subject('New vote for your review!')
->greeting("Hello, {$notifiable->name}!")
->line("We got a new vote for your review for {$this->serverReview->server->name} server!")
->line("Your review currently have {$this->serverReview->votesUpCount()} upvotes and {$this->serverReview->votesDownCount()} downvotes.")
->line("Click the button below to navigate to the server page:")
->action($this->serverReview->server->name, route('servers.show', ['server' => $this->serverReview->server->slug]));
}
}
现在监听器成功调度到jobs
表,可以通过运行php artisan queue:work database
进行处理
对于遇到类似问题的任何其他人,事件/侦听器同步启动,而不是按预期异步启动,而是他们的侦听器实现ShouldQueue
对我来说,我错过了活动中的Dispatchable
。
<?php
namespace AppEvents;
use IlluminateQueueSerializesModels;
use IlluminateFoundationEventsDispatchable;
class LogEvent
{
use Dispatchable, SerializesModels;
public function __construct()
{
//
}
}
<?php
namespace AppListeners;
use IlluminateContractsQueueShouldQueue;
class LogEventListener implements ShouldQueue
{
public function __construct()
{
//
}
public function handle(): void
{
//
}
}
可调度&ShouldQueue=
Horizon started successfully.
2023-07-25 18:32:43 AppListenersLogEventListener ................. RUNNING
2023-07-25 18:32:43 AppListenersLogEventListener ........... 518.59ms DONE
2023-07-25 18:33:13 AppListenersLogEventListener ................. RUNNING
2023-07-25 18:33:14 AppListenersLogEventListener ........... 255.91ms DONE