Skip to content

Commit 87b6cbc

Browse files
committed
producers and consumers autowiring arguments
registering aliases for autowiring arguments when loading producers and consumers from configuration.
1 parent da40764 commit 87b6cbc

File tree

3 files changed

+126
-6
lines changed

3 files changed

+126
-6
lines changed

DependencyInjection/OldSoundRabbitMqExtension.php

Lines changed: 38 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -3,13 +3,13 @@
33
namespace OldSound\RabbitMqBundle\DependencyInjection;
44

55
use Symfony\Component\Config\Definition\Exception\InvalidConfigurationException;
6-
use Symfony\Component\DependencyInjection\ContainerInterface;
7-
use Symfony\Component\DependencyInjection\Extension\Extension;
6+
use Symfony\Component\Config\FileLocator;
87
use Symfony\Component\DependencyInjection\ContainerBuilder;
8+
use Symfony\Component\DependencyInjection\ContainerInterface;
99
use Symfony\Component\DependencyInjection\Definition;
10-
use Symfony\Component\DependencyInjection\Reference;
10+
use Symfony\Component\DependencyInjection\Extension\Extension;
1111
use Symfony\Component\DependencyInjection\Loader\XmlFileLoader;
12-
use Symfony\Component\Config\FileLocator;
12+
use Symfony\Component\DependencyInjection\Reference;
1313

1414
/**
1515
* OldSoundRabbitMqExtension.
@@ -171,11 +171,32 @@ protected function loadProducers()
171171
if (null !== $producer['service_alias']) {
172172
$this->container->setAlias($producer['service_alias'], $producerServiceName);
173173
}
174+
175+
// register alias for argument auto wiring
176+
if (method_exists($this->container, 'registerAliasForArgument')) {
177+
$argName = !str_ends_with(strtolower($key), 'producer') ? sprintf('%sProducer', $key) : $key;
178+
$this->container
179+
->registerAliasForArgument($producerServiceName, 'OldSound\RabbitMqBundle\RabbitMq\ProducerInterface', $argName)
180+
->setPublic(false);
181+
182+
$this->container
183+
->registerAliasForArgument($producerServiceName, $producer['class'], $argName)
184+
->setPublic(false);
185+
}
174186
}
175187
} else {
176188
foreach ($this->config['producers'] as $key => $producer) {
177189
$definition = new Definition('%old_sound_rabbit_mq.fallback.class%');
178-
$this->container->setDefinition(sprintf('old_sound_rabbit_mq.%s_producer', $key), $definition);
190+
$producerServiceName = sprintf('old_sound_rabbit_mq.%s_producer', $key);
191+
$this->container->setDefinition($producerServiceName, $definition);
192+
193+
// register alias for argumen auto wiring
194+
if (method_exists($this->container, 'registerAliasForArgument')) {
195+
$argName = !str_ends_with(strtolower($key), 'producer') ? sprintf('%sProducer', $key) : $key;
196+
$this->container
197+
->registerAliasForArgument($producerServiceName, 'OldSound\RabbitMqBundle\RabbitMq\ProducerInterface', $argName)
198+
->setPublic(false);
199+
}
179200
}
180201
}
181202
}
@@ -242,6 +263,18 @@ protected function loadConsumers()
242263
$name = sprintf('old_sound_rabbit_mq.%s_consumer', $key);
243264
$this->container->setDefinition($name, $definition);
244265
$this->addDequeuerAwareCall($consumer['callback'], $name);
266+
267+
// register alias for argument auto wiring
268+
if (method_exists($this->container, 'registerAliasForArgument')) {
269+
$argName = !str_ends_with(strtolower($key), 'consumer') ? sprintf('%sConsumer', $key) : $key;
270+
$this->container
271+
->registerAliasForArgument($name, 'OldSound\RabbitMqBundle\RabbitMq\ConsumerInterface', $argName)
272+
->setPublic(false);
273+
274+
$this->container
275+
->registerAliasForArgument($name, '%old_sound_rabbit_mq.consumer.class%', $argName)
276+
->setPublic(false);
277+
}
245278
}
246279
}
247280

README.md

Lines changed: 30 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -534,6 +534,35 @@ consumers:
534534
qos_options: {prefetch_size: 0, prefetch_count: 1, global: false}
535535
```
536536

537+
### Autowiring producers and consumers ###
538+
539+
If used with **Symfony 4.2+** bundle declares in container set of aliases for producers and regular consumers. Those are
540+
used for arguments autowiring based on declared type and argument name. This allows you to change previous producer
541+
example to:
542+
543+
```php
544+
public function indexAction($name, ProducerInteface $uploadPictureProducer)
545+
{
546+
$msg = array('user_id' => 1235, 'image_path' => '/path/to/new/pic.png');
547+
$uploadPictureProducer->publish(serialize($msg));
548+
}
549+
```
550+
551+
Name of argument is constructed from producer or consumer name from configuration and suffixed with producer or consumer
552+
word according to type. In contrast to container items naming convention word suffix (producer or consumer) will not be
553+
duplicated if name is already suffixed. `upload_picture` producer key will be changed to `$uploadPictureProducer`
554+
argument name. `upload_picture_producer` producer key would also be aliased to `$uploadPictureProducer` argument name.
555+
It is best to avoid names similar in such manner.
556+
557+
All producers are aliased to `OldSound\RabbitMqBundle\RabbitMq\ProducerInterface` and producer class option from
558+
configuration. In sandbox mode only ProducerInterface aliases are made. It is highly recommended to use ProducerInterface
559+
class when type hinting arguments for producer injection.
560+
561+
All consumers are aliased to 'OldSound\RabbitMqBundle\RabbitMq\ConsumerInterface' and '%old_sound_rabbit_mq.consumer.class%'
562+
configuration option value. There is no difference between regular and sandbox mode. It is highly recommended to use
563+
ConsumerInterface when type hinting arguments for client injection.
564+
565+
537566
### Callbacks ###
538567

539568
Here's an example callback:
@@ -807,7 +836,7 @@ binding scenarios might include exchange to exchange bindings via `destination_i
807836
```yaml
808837
bindings:
809838
- {exchange: foo, destination: bar, routing_key: 'baz.*' }
810-
- {exchange: foo1, destination: foo, routing_key: 'baz.*' destination_is_exchange: true}
839+
- {exchange: foo1, destination: foo, routing_key: 'baz.*', destination_is_exchange: true}
811840
```
812841

813842
The rabbitmq:setup-fabric command will declare exchanges and queues as defined in your producer, consumer

Tests/DependencyInjection/OldSoundRabbitMqExtensionTest.php

Lines changed: 58 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@
33
namespace OldSound\RabbitMqBundle\Tests\DependencyInjection;
44

55
use Symfony\Component\DependencyInjection\ContainerBuilder;
6+
use Symfony\Component\DependencyInjection\ContainerInterface;
67
use Symfony\Component\DependencyInjection\Definition;
78
use Symfony\Component\DependencyInjection\ParameterBag\ParameterBag;
89
use Symfony\Component\Config\FileLocator;
@@ -318,6 +319,36 @@ public function testFooProducerDefinition()
318319
$this->assertEquals('My\Foo\Producer', $definition->getClass());
319320
}
320321

322+
public function testProducerArgumentAliases()
323+
{
324+
/** @var ContainerInterface $container */
325+
$container = $this->getContainer('test.yml');
326+
327+
if (!method_exists($container, 'registerAliasForArgument')) {
328+
// don't test if autowiring arguments functionality is not available
329+
return;
330+
}
331+
332+
// test expected aliases
333+
$producerInterface = 'OldSound\RabbitMqBundle\RabbitMq\ProducerInterface';
334+
$expectedAliases = array(
335+
$producerInterface . ' $fooProducer' => 'old_sound_rabbit_mq.foo_producer_producer',
336+
'My\Foo\Producer $fooProducer' => 'old_sound_rabbit_mq.foo_producer_producer',
337+
$producerInterface . ' $fooProducerAliasedProducer' => 'old_sound_rabbit_mq.foo_producer_aliased_producer',
338+
'My\Foo\Producer $fooProducerAliasedProducer' => 'old_sound_rabbit_mq.foo_producer_aliased_producer',
339+
$producerInterface . ' $defaultProducer' => 'old_sound_rabbit_mq.default_producer_producer',
340+
'%old_sound_rabbit_mq.producer.class% $defaultProducer' => 'old_sound_rabbit_mq.default_producer_producer',
341+
);
342+
343+
foreach($expectedAliases as $id => $target) {
344+
$this->assertTrue($container->hasAlias($id), sprintf('Container should have %s alias for autowiring support.', $id));
345+
346+
$alias = $container->getAlias($id);
347+
$this->assertEquals($target, (string)$alias, sprintf('Autowiring for %s should use %s.', $id, $target));
348+
$this->assertFalse($alias->isPublic(), sprintf('Autowiring alias for %s should be private', $id));
349+
}
350+
}
351+
321352
/**
322353
* @group alias
323354
*/
@@ -427,6 +458,33 @@ public function testFooConsumerDefinition()
427458
$this->assertEquals('%old_sound_rabbit_mq.consumer.class%', $definition->getClass());
428459
}
429460

461+
public function testConsumerArgumentAliases()
462+
{
463+
$container = $this->getContainer('test.yml');
464+
465+
if (!method_exists($container, 'registerAliasForArgument')) {
466+
// don't test if autowiring arguments functionality is not available
467+
return;
468+
}
469+
470+
$consumerInterface = 'OldSound\RabbitMqBundle\RabbitMq\ConsumerInterface';
471+
$expectedAliases = array(
472+
$consumerInterface . ' $fooConsumer' => 'old_sound_rabbit_mq.foo_consumer_consumer',
473+
'%old_sound_rabbit_mq.consumer.class% $fooConsumer' => 'old_sound_rabbit_mq.foo_consumer_consumer',
474+
$consumerInterface . ' $defaultConsumer' => 'old_sound_rabbit_mq.default_consumer_consumer',
475+
'%old_sound_rabbit_mq.consumer.class% $defaultConsumer' => 'old_sound_rabbit_mq.default_consumer_consumer',
476+
$consumerInterface . ' $qosTestConsumer' => 'old_sound_rabbit_mq.qos_test_consumer_consumer',
477+
'%old_sound_rabbit_mq.consumer.class% $qosTestConsumer' => 'old_sound_rabbit_mq.qos_test_consumer_consumer'
478+
);
479+
foreach($expectedAliases as $id => $target) {
480+
$this->assertTrue($container->hasAlias($id), sprintf('Container should have %s alias for autowiring support.', $id));
481+
482+
$alias = $container->getAlias($id);
483+
$this->assertEquals($target, (string)$alias, sprintf('Autowiring for %s should use %s.', $id, $target));
484+
$this->assertFalse($alias->isPublic(), sprintf('Autowiring alias for %s should be private', $id));
485+
}
486+
}
487+
430488
public function testDefaultConsumerDefinition()
431489
{
432490
$container = $this->getContainer('test.yml');

0 commit comments

Comments
 (0)