【问题标题】:How to access EntityManager into a RabbitMQBundle custom producer class?如何将 EntityManager 访问到 RabbitMQBundle 自定义生产者类?
【发布时间】:2017-07-04 16:28:20
【问题描述】:

我在 Symfony 2.8 项目中使用RabbitMQBundle,并且我想使用自定义生产者类,它在发布 RabbitMQ 消息之前将实体(消息)保存在数据库中。

我在 config.yml 中定义了自定义生产者类:

old_sound_rabbit_mq:
  ...
  producers:
    myproducer:
      class: AppBundle\Services\GenericProducer
      connection: default
      exchange_options: {name: 'my_exchange', type: direct}

还有自定义的 Producer 类:

<?php

namespace AppBundle\Services;

use AppBundle\Entity\Message;
use OldSound\RabbitMqBundle\RabbitMq\Producer;

/**
 * Customised Producer, that publishes AMQP Messages
 * but also:
 * - writes an entry in the Message table
 */
class GenericProducer extends Producer
{
    /**
     * Entity Manager
     */
    protected $em;


    public function setEntityManager($entityManager)
    {
        $this->em = $entityManager;

        return $this;
    }

    /**
     * Publishes the message and merges additional properties with basic properties
     * And also:
     * - writes an entry in the Message table
     *
     * @param string $action
     * @param array $parameters
     * @param string $routingKey
     * @param array $additionalProperties
     * @param array|null $headers
     */
    public function publish($action, $parameters = array() , $routingKey = '', $additionalProperties = array(), array $headers = null)
    {
        $message = new Message();
        $message->setAction($action)
            ->setParameters($parameters);
        $this->em->persist($message);
        $this->em->flush();

        $msgBody = array(
            'action' => $action,
            'parameters' => $parameters
        );
        parent::publish($msgBody, $routingKey, $additionalProperties, $headers);
    }
}

我如何拨打GenericProducer-&gt;setEntityManager,因为生产者没有在 services.yml 中定义,就像其他服务一样?

还有其他方法可以实现吗?

感谢您的宝贵时间。

【问题讨论】:

    标签: php symfony rabbitmq symfony-2.8


    【解决方案1】:

    生产者服务定义由Dependency Injection Extension of the bundle中的bundle动态生成。

    您可以尝试decorate the existing service 或创建一个compiler pass,在其中获取现有服务并通过调用setEntityManager 函数对其进行扩展。

    【讨论】:

    • 谢谢,我按照装饰者的方式。我在答案中显示了完整的代码。
    【解决方案2】:

    根据@lordrhodos 的建议,我装饰了由 RabbitMQBundle 生成的生产者服务。以下是完整代码:

    config.yml(没什么特别的):

    old_sound_rabbit_mq:
      ...
      producers:
        myproducer:
          connection: default
          exchange_options: {name: 'my_exchange', type: direct} 
    

    services.yml(在这里定义装饰服务):

    app.decorating_myproducer_producer:
          class: AppBundle\Services\GenericProducer
          decorates: old_sound_rabbit_mq.myproducer_producer
          arguments: ['@
    app.decorating_myproducer_producer.inner', '@doctrine.orm.entity_manager']
          public: false
    

    装饰类

    <?php
    
    namespace AppBundle\Services;
    
    use AppBundle\Entity\Message;
    use OldSound\RabbitMqBundle\RabbitMq\Producer;
    
    /**
     * Customised Producer, that publishes AMQP Messages
     * but also:
     * - writes an entry in the Message table
     */
    class GenericProducer extends Producer
    {
        /**
         * @var Producer
         */
        protected $producer;
    
        /**
         * @var EntityManager
         */
        protected $em;
    
        /**
         * GenericProducer constructor.
         * @param Producer $producer
         * @param EntityManager $entityManager
         */
        public function __construct(Producer $producer, EntityManager $entityManager)
        {
            $this->producer = $producer;
            $this->em = $entityManager;
        }
    
    
        /**
         * Publishes the message and merges additional properties with basic properties
         * And also:
         * - writes an entry in the Message table
         *
         * @param string $action
         * @param array $parameters
         * @param string $routingKey
         * @param array $additionalProperties
         * @param array|null $headers
         */
        public function publish($action, $parameters = array() , $routingKey = '', $additionalProperties = array(), array $headers = null)
        {
            $message = new Message();
            $message->setAction($action)
                ->setParameters($parameters);
            $this->em->persist($message);
            $this->em->flush();
    
            $msgBody = array(
                'action' => $action,
                'parameters' => $parameters
            );
            $this->producer->publish(serialize($msgBody), $routingKey, $additionalProperties, $headers);
    
        }
    }
    

    最后,从控制器调用原始生产者:

    $this->get('old_sound_rabbit_mq.myproducer_producer')->publish('wait', ['time' => 30]);
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2015-10-20
      • 1970-01-01
      • 2020-08-27
      • 2021-10-18
      • 1970-01-01
      • 2015-10-03
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多