代码之家  ›  专栏  ›  技术社区  ›  scandel

如何将EntityManager访问到RabbitMQBundle自定义生产者类?

  •  1
  • scandel  · 技术社区  · 9 年前

    RabbitMQBundle 在Symfony 2.8项目中,我想使用一个自定义生产者类,它在发布RabbitMQ消息之前将实体(消息)持久化到数据库中。

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

    以及定制制作人类:

    <?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->setEntityManager ,因为服务中未定义生产者。yml和其他服务一样?

    有没有其他方法可以实现这一点?

    2 回复  |  直到 9 年前
        1
  •  1
  •   lordrhodos    9 年前

    生产者服务定义由 Dependency Injection Extension of the bundle

    你可以试着 decorate the existing service 或创建 compiler pass 获取现有服务并通过调用 setEntityManager

        2
  •  0
  •   scandel    9 年前

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

    config.yml

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

    服务.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]);