通过 Symfony Messenger 执行邮件发送

Executing mail sending via Symfony Messenger

我正在寻找对我的代码有很大帮助的人。 我尽我所能连接一些 Symfony 功能,我想我要去某个地方..

我正在使用 Symfony 4.2 和 API 平台并尝试添加异步使用电子邮件消息发送的过程。

我有我的 Comment 实体,它在持久实体上触发它。它触发了我的 __invoke 函数,但出现了问题。我不太明白下一步该怎么做。

正如文档 here 中所述,首先我需要配置 Data Persister:

<?php

namespace App\DataPersister;

use ApiPlatform\Core\DataPersister\ContextAwareDataPersisterInterface;
use ApiPlatform\Core\DataPersister\DataPersisterInterface;
use App\Entity\Comment;

final class EmailNotificationDataPersister implements ContextAwareDataPersisterInterface
{
private $decorated;
private $mailer;

public function __construct(ContextAwareDataPersisterInterface $decorated, \Swift_Mailer $mailer)
{
    $this->decorated = $decorated;
    $this->mailer = $mailer;
}

public function supports($data, array $context = []): bool
{
    return $this->decorated->supports($data, $context);
}

public function persist($data, array $context = [])
{
    $result = $this->decorated->persist($data, $context);

    if (
        $data instanceof Comment && (
            ($context['collection_operation_name'] ?? null) === 'post')
    ) {
        $this->sendWelcomeEmail($data);
    }

    return $result;
}

public function remove($data, array $context = [])
{
    return $this->decorated->remove($data, $context);
}

private function sendWelcomeEmail(Comment $comment)
{
    // Your welcome email logic...
    // $this->mailer->send(...);
}
}

我使用的是 Symfony 4.2,所以我安装了 swift 邮件客户端。

我还定义了 EmailSubscriber:

<?php

namespace App\EventSubscriber;

use ApiPlatform\Core\EventListener\EventPriorities;
use App\Entity\Comment;
use Symfony\Component\EventDispatcher\EventSubscriberInterface;
use Symfony\Component\HttpFoundation\Request;
use Symfony\Component\HttpKernel\KernelEvents;
use Symfony\Component\HttpKernel\Event\GetResponseForControllerResultEvent;
use Symfony\Component\Messenger\MessageBusInterface;

final class EmailNotificationSubscriber implements EventSubscriberInterface

{

private $messageBus;

public function __construct(MessageBusInterface $messageBus)
{
    $this->messageBus = $messageBus;
}

public static function getSubscribedEvents()
{
    return [
        KernelEvents::VIEW => [ 'sendMail', EventPriorities::POST_WRITE],
    ];
}

public function sendMail(GetResponseForControllerResultEvent $event)
{
    $comment = $event->getControllerResult();
    $method = $event->getRequest()->getMethod();


    if (!$comment instanceof Comment || Request::METHOD_POST !== $method) {
        return;
    }

    $this->messageBus->dispatch(new Comment());
}
}

最后我实现了处理程序:

<?php

namespace App\Handler;

use App\Entity\Comment;
use Symfony\Component\Messenger\Handler\MessageHandlerInterface;

final class EmailNotificationHandler implements MessageHandlerInterface
{
    public function __invoke(Comment $comment)
    {
        // do something with the resource
    }
}

当我在我的 api 平台中触发持久化实体时,调用函数中的 var_dump() 被捕获。

我不知道是不是出了什么问题,接下来我该怎么做。 我需要使用 Symfony Messenger 异步执行电子邮件发送。

在我的 .env 文件中:

MESSENGER_TRANSPORT_DSN=amqp://127.0.0.1:8000/api/messages

和框架.yaml

messenger:
    transports:
        amqp: "%env(MESSENGER_TRANSPORT_DSN)%"

    routing:
        'App\Entity\Comment': amqp

还有什么方法可以向用户 table 中发布的任意随机邮件发送电子邮件?我想为此设置邮件程序配置。

对于 运行 异步操作,您需要 transport。对于本地测试 symfony 服务器和 docker 效果很好。

#config/packages/messenger.yaml
transports:
    async: '%env(RABBITMQ_DSN)%'

docker-compose.yaml 放在项目根目录。

rabbitmq:
    image: rabbitmq:3-management
    ports: [5672, 15672]

运行 在控制台中

docker-compose up -d
symfony server:start -d

用于在控制台

中使用消息运行
symfony console messenger:consume async -vv

在生产环境中,您必须为 RabbitMQ、Amazon SQS 等添加 RABBITMQ_DSN(或 MESSENGER_TRANSPORT_DSN),并可能使用 Supervisor 来使用消息。