如何将EntityManager访问到RabbitMQBundle自定义生成器类中?

时间:2017-07-04 16:28:20

标签: php symfony rabbitmq symfony-2.8

我在Symfony 2.8项目中使用RabbitMQBundle,我想使用一个自定义生成器类,它在发布RabbitMQ消息之前将实体(Message)保留在数据库中。

我在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->setEntityManager,因为生产者未在services.yml中定义,就像其他服务一样?

还有另一种方法可以达到这个目的吗?

感谢您的时间。

2 个答案:

答案 0 :(得分:1)

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

您可以尝试decorate the existing service或创建compiler pass来获取现有服务,并通过调用wc -l tags 函数对其进行扩展。

答案 1 :(得分:0)

关于@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]);