Skip to content

Commit cbb4c8d

Browse files
authored
Added service aliases to allow easier autowiring (#301)
Added service aliases to allow easier autowiring
1 parent fb0c746 commit cbb4c8d

File tree

3 files changed

+64
-5
lines changed

3 files changed

+64
-5
lines changed

src/DependencyInjection/EightPointsGuzzleExtension.php

Lines changed: 14 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@
44

55
use EightPoints\Bundle\GuzzleBundle\Log\Logger;
66
use EightPoints\Bundle\GuzzleBundle\Twig\Extension\DebugExtension;
7+
use GuzzleHttp\ClientInterface;
78
use Symfony\Component\DependencyInjection\ContainerBuilder;
89
use Symfony\Component\DependencyInjection\Loader\XmlFileLoader;
910
use Symfony\Component\DependencyInjection\Reference;
@@ -91,13 +92,21 @@ public function load(array $configs, ContainerBuilder $container)
9192
// set service name based on client name
9293
$serviceName = sprintf('%s.client.%s', $this->getAlias(), $name);
9394
$container->setDefinition($serviceName, $client);
95+
96+
// Allowed only for Symfony 4.2+
97+
if (method_exists($container, 'registerAliasForArgument')) {
98+
if ('%eight_points_guzzle.http_client.class%' !== $options['class']) {
99+
$container->registerAliasForArgument($serviceName, $options['class'], $name . 'Client');
100+
}
101+
$container->registerAliasForArgument($serviceName, ClientInterface::class, $name . 'Client');
102+
}
94103
}
95104

96-
$clientsWithLogging = array_filter($config['clients'], function ($options) use ($logging) {
105+
$clientsWithLogging = array_filter($config['clients'], function($options) use ($logging) {
97106
return $options['logging'] !== false && $logging !== false;
98107
});
99108

100-
if (count($clientsWithLogging)>0) {
109+
if (count($clientsWithLogging) > 0) {
101110
$this->defineTwigDebugExtension($container);
102111
$this->defineDataCollector($container, $config['slow_response_time'] / 1000);
103112
$this->defineFormatter($container);
@@ -125,7 +134,7 @@ protected function createHandler(ContainerBuilder $container, string $clientName
125134
$container->setDefinition($eventServiceName, $eventService);
126135

127136
// Create the event Dispatch Middleware
128-
$eventExpression = new Expression(sprintf("service('%s').dispatchEvent()", $eventServiceName));
137+
$eventExpression = new Expression(sprintf("service('%s').dispatchEvent()", $eventServiceName));
129138

130139
$handler = new Definition(HandlerStack::class);
131140
$handler->setFactory([HandlerStack::class, 'create']);
@@ -173,7 +182,7 @@ protected function createHandler(ContainerBuilder $container, string $clientName
173182
*/
174183
private function convertLogMode($logMode) : int
175184
{
176-
if ($logMode === true){
185+
if ($logMode === true) {
177186
return Logger::LOG_MODE_REQUEST_AND_RESPONSE;
178187
} elseif ($logMode === false) {
179188
return Logger::LOG_MODE_NONE;
@@ -230,7 +239,7 @@ protected function defineLogger(ContainerBuilder $container, int $logMode, strin
230239
protected function defineDataCollector(ContainerBuilder $container, float $slowResponseTime) : void
231240
{
232241
$dataCollectorDefinition = new Definition('%eight_points_guzzle.data_collector.class%');
233-
$dataCollectorDefinition->addArgument(array_map(function ($loggerId) : Reference {
242+
$dataCollectorDefinition->addArgument(array_map(function($loggerId) : Reference {
234243
return new Reference($loggerId);
235244
}, array_keys($container->findTaggedServiceIds('eight_points_guzzle.logger'))));
236245

src/Resources/doc/autowiring-clients.md

Lines changed: 38 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,44 @@ Autowiring was introduced in Symfony 3.3 and let's read how [Symfony Documentati
44

55
> Autowiring allows you to manage services in the container with minimal configuration. It reads the type-hints on your constructor (or other methods) and automatically passes the correct services to each method. Symfony's autowiring is designed to be predictable: if it is not absolutely clear which dependency should be passed, you'll see an actionable exception.
66
7+
## Symfony >= 4.2
8+
In Symfony 4.2, it is made possible to [bind services by type and name](https://symfony.com/blog/new-in-symfony-4-2-autowiring-by-type-and-name). This feature makes using Guzzle clients a lot easier. Given the following configuration:
9+
10+
```yaml
11+
eight_points_guzzle:
12+
clients:
13+
api_payment:
14+
base_url: "http://api.domain1.tld"
15+
api_crm:
16+
class: App\Client\ApiCrmClient
17+
base_url: "http://api.domain2.tld"
18+
```
19+
The clients can be autowired without further configuration (but mandatory variable names), like this:
20+
21+
```php
22+
namespace App\Controller;
23+
24+
use GuzzleHttp\ClientInterface;
25+
use App\Client\ApiCrmClient;
26+
27+
class FooController extends AbstractController
28+
{
29+
public function bar(ClientInterface $apiPaymentClient)
30+
{
31+
// Default Client class
32+
}
33+
34+
public function baz(ApiCrmClient $apiCrmClient)
35+
{
36+
// Custom Client class (must extend GuzzleHttp\Client)
37+
}
38+
}
39+
```
40+
41+
Autowiring takes place by the combination of the class name and the variable name, as described in [this blog].
42+
43+
## Symfony < 4.2
44+
745
Getting in consideration, that Guzzle Bundle creates clients of same class, it becomes obvious that Symfony will not be able to guess what to inject.
846
With some small configurations we can help Symfony to do it.
947

tests/DependencyInjection/EightPointsGuzzleExtensionTest.php

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -34,6 +34,13 @@ public function testGuzzleExtension()
3434
$this->assertInstanceOf(Client::class, $testApi);
3535
$this->assertEquals(new Uri('//api.domain.tld/path'), $testApi->getConfig('base_uri'));
3636

37+
if (method_exists($container, 'registerAliasForArgument')) {
38+
$this->assertTrue($container->hasAlias(ClientInterface::class . ' $testApiClient'));
39+
$this->assertSame($testApi, $container->get(ClientInterface::class . ' $testApiClient'));
40+
41+
$this->assertFalse($container->hasAlias('%eight_points_guzzle.http_client.class% $testApiClient'));
42+
}
43+
3744
// test Services
3845
$this->assertTrue($container->hasDefinition('eight_points_guzzle.middleware.event_dispatch.test_api'));
3946

@@ -42,6 +49,11 @@ public function testGuzzleExtension()
4249
$definition = $container->getDefinition('eight_points_guzzle.client.test_api_with_custom_class');
4350
$this->assertSame(CustomClient::class, $definition->getClass());
4451

52+
if (method_exists($container, 'registerAliasForArgument')) {
53+
$testApi = $container->get('eight_points_guzzle.client.test_api_with_custom_class');
54+
$this->assertTrue($container->hasAlias(CustomClient::class . ' $testApiWithCustomClassClient'));
55+
$this->assertSame($testApi, $container->get(ClientInterface::class . ' $testApiWithCustomClassClient'));
56+
}
4557

4658
// test Client with custom handler
4759
$this->assertTrue($container->hasDefinition('eight_points_guzzle.client.test_api_with_custom_handler'));

0 commit comments

Comments
 (0)