我使用的是API平台3.1.我需要在创建后生成一些实体的缩略图.我想使用Symfony Messenger来触发它,并异步完成它,因为它可能需要一些时间来处理,但我希望立即保存实体.

当资源同时使用Messenger和自定义处理器(以保存实体)时,如果使用messenger=true,则不创建消息;如果使用messenger='input',则不调用处理器.

How to reproduce

#[ORM\Entity]
#[ApiResource(
    operations: [
        new Post(
            processor: MyEntityProcessor::class,
            messenger: 'input',
            deserialize: false, 
        )
    ]
)]
class MyEntity
{
}
final class MyEntityProcessor implements ProcessorInterface
{
    public function __construct(private ProcessorInterface $persistProcessor)
    {
    }

    public function process($data, Operation $operation, array $uriVariables = [], array $context = [])
    {
        $result = $this->persistProcessor->process($data, $operation, $uriVariables, $context);
        return $result;
    }
}
final class MyEntityHandler implements MessageHandlerInterface
{
    public function __construct(private EntityManagerInterface $entityManager)
    {
    }

    public function __invoke(MyEntity $myEntity)
    {
        // my long running function

        $this->entityManager->persist($myEntity);
        $this->entityManager->flush();
    }
}

services.yaml

services:
    App\State\MyEntityProcessor:
        bind:
            $persistProcessor: '@api_platform.doctrine.orm.state.item_provider'

messenger.yaml

framework:
    messenger:
        transports:
            async: 'doctrine://default'

        routing:
            'App\Entity\MyEntity': async

API平台文档在Symfony Messenger Integration篇文章中提到:

注意:在Doctrine实体中使用messenger=true ApiResource属性时,不会调用Doctrine处理器.如果您希望Doctrine处理器被调用,您应该decorate a built-in state processor并实现您自己的逻辑.

这是suggested on a GitHub issue,我应该装饰信使处理程序,以拯救实体.然而,我需要立即保存我的实体,而不是等待它被messenger:consume工作人员使用.

推荐答案

一种可能的解决方案是在您第一次保留Entity之后,在您的Processor中发送Message.可能不是那么干净,因为它需要更多的代码,但您可以更多地控制如何以及何时处理Message.此外,您也可以用DelayStamp来发送它.

在您的处理器中,我会像这样dispatch the Message:

final class MyEntityProcessor implements ProcessorInterface
{
    
    public function __construct(
        private ProcessorInterface $persistProcessor,
        private MessageBusInterface $bus,
    ) {
    }

    public function process($data, Operation $operation, array $uriVariables = [], array $context = [])
    {
        $result = $this->persistProcessor->process($data, $operation, $uriVariables, $context);

        // $data should be your MyEntity Entity.
        $this->bus->dispatch(new GenerateThumbMessage($data), [
            // wait 5 seconds before processing
            new DelayStamp(5000),
        ]);
        
        return $result;
    }
}

Create the Message,App\Message\GenerateThumbMessage.php:

class GenerateThumbMessage
{

    public function __construct(private readonly MyEntity $myEntity) {}

    public function getMyEntity(): MyEntity
    {
        return $this->myEntity;
    }

}

然后是create your MessageHandler App\Message\GenerateThumbMessageHandler.php:

final class GenerateThumbMessageHandler implements MessageHandlerInterface
{
    public function __construct(private EntityManagerInterface $em) {}

    public function __invoke(GenerateThumbMessage $generateThumbMessage)
    {
        $myEntity = $generateThumbMessage->getMyEntity();
        
        // your long running function to generate a thumbnail

        $this->em->persist($myEntity);
        $this->em->flush();
    }
}

您的messenger.yaml配置应该如下所示:

framework:
    messenger:
        transports:
            async: 'doctrine://default'

        routing:
            'App\Message\GenerateThumbMessage': async

在配置中,您已将Message配置为进行异步处理,而不是使用Entity.

类似的解决方案可以在API Platform documentation

Php相关问答推荐

PHP Perl正则表达式—URL前面没有等号和可能的单引号或双引号

在ShipStation for WooCommerce中使用自定义订单项目元数据

如何显示每个分类的当前术语的帖子中包含的前20个标签,不包括标签分类

在PHP中读取JSON

如何使用索引加速和优化MySQL搜索

我有一个显示记录的表格,每行在最右边有两个按钮.如何才能以正确的顺序获得表的值?

使用与OpenSSL命令行兼容的AES-256-CTR为大型文件创建php代码OpenSSL加密

如何使用barryvdh/laravel-Snappy在两个打印页面上将表格分成两部分?

Regex:高级删除单行PHP注释

文件::Files()响应返回空对象数组

PHP按另一个二维数组的排序顺序对二维数组进行排序

在WooCommercel邮箱通知上添加来自Apaczka插件的选定交付点

对 WooCommerce 购物车和 checkout 中显示的运输方式进行排序

如何在 Woocommerce 中自动删除旧的已完成订单

PHP 在数组中搜索值

在 PHP 8.2 中使用 PHP Spreadsheet 和 CodeIgniter 3 导出 Excel 时出错

在 groupBy laravel 5.7 中 Select 多列

如何设置Mailersend PHP API 模板变量?

在WooCommerce我的账户单个订单页面中添加订单商品部分和按钮

复杂的mysql查询问题