misd/guzzle-bundle
Symfony2 bundle integrating Guzzle 3 for easy HTTP requests and reusable web service clients. Optional integration with JMSSerializerBundle for object (de)serialization plus a SensioFrameworkExtraBundle param converter for streamlined controllers.
Installation
Add the bundle to composer.json:
composer require misd/guzzle-bundle
Enable in config/bundles.php:
return [
// ...
Misd\GuzzleBundle\MisdGuzzleBundle::class => ['all' => true],
];
Basic Configuration
Define a client in config/packages/misd_guzzle.yaml:
misd_guzzle:
clients:
default:
base_url: 'https://api.example.com'
timeout: 30
options:
headers:
Accept: 'application/json'
First Use Case: HTTP Request Inject the client into a service/controller:
use Misd\GuzzleBundle\Client\ClientInterface;
class MyController
{
public function __construct(private ClientInterface $client)
{
}
public function fetchData()
{
$response = $this->client->get('endpoint');
$data = json_decode($response->getBody(), true);
return $this->render('template.html.twig', ['data' => $data]);
}
}
Create dedicated services for API interactions:
// src/Service/ExternalApiService.php
namespace App\Service;
use Misd\GuzzleBundle\Client\ClientInterface;
class ExternalApiService
{
public function __construct(private ClientInterface $client)
{
}
public function getUserData(int $id): array
{
$response = $this->client->get("/users/{$id}");
return json_decode($response->getBody(), true);
}
}
Use with SensioFrameworkExtraBundle for automatic request handling:
# config/packages/misd_guzzle.yaml
misd_guzzle:
param_converter:
enabled: true
clients:
- default
Annotate controller actions:
use Sensio\Bundle\FrameworkExtraBundle\Configuration\ParamConverter;
class UserController
{
/**
* @ParamConverter("user", converter="misd_guzzle.param_converter")
*/
public function show(User $user)
{
// $user is automatically fetched via API
}
}
Enable serialization/deserialization:
# config/packages/misd_guzzle.yaml
misd_guzzle:
clients:
default:
serializer:
enabled: true
options:
groups: ['api']
Use in services:
$user = $this->client->get('/users/1', User::class);
Extend the client with middleware (e.g., logging, retries):
# config/packages/misd_guzzle.yaml
misd_guzzle:
clients:
default:
middleware:
- Misd\GuzzleBundle\Middleware\LoggingMiddleware
- Misd\GuzzleBundle\Middleware\RetryMiddleware
Use Guzzle’s async capabilities:
$promises = [];
$promises[] = $this->client->getAsync('endpoint1');
$promises[] = $this->client->postAsync('endpoint2', ['data' => []]);
$results = \Guzzle\Promise\Utils::settle($promises)->wait();
Requests are automatically logged in the Symfony Profiler under the "Guzzle" tab. Useful for debugging:
Prefer type-hinting ClientInterface over concrete implementations for flexibility:
public function __construct(private ClientInterface $client)
Override client configurations per environment (e.g., config/packages/dev/misd_guzzle.yaml):
misd_guzzle:
clients:
default:
base_url: 'https://dev-api.example.com'
timeout: 60
Mock the ClientInterface in tests:
$mockClient = $this->createMock(ClientInterface::class);
$mockClient->method('get')->willReturn(new Response(200, [], '{}'));
$service = new ExternalApiService($mockClient);
php-http/guzzle6-adapter or migrate to a modern bundle like nelmio/api-client-bundle.ParamConverter requires SensioFrameworkExtraBundle. If missing, disable it in config:
misd_guzzle:
param_converter:
enabled: false
JMSSerializerBundle is installed and configured before enabling serialization:
composer require jms/serializer-bundle
php bin/console debug:container misd_guzzle.client.default
misd_guzzle:
profiler:
enabled: false
misd_guzzle:
clients:
default:
timeout: 120
Add to config/packages/dev/misd_guzzle.yaml:
misd_guzzle:
debug: true
Use the LoggingMiddleware:
misd_guzzle:
clients:
default:
middleware:
- Misd\GuzzleBundle\Middleware\LoggingMiddleware
options:
logging: true
Logs appear in var/log/dev.log.
Check for syntax errors:
php bin/console debug:config misd_guzzle
Catch Misd\GuzzleBundle\Exception\ClientException and Misd\GuzzleBundle\Exception\ServerException:
try {
$response = $this->client->get('endpoint');
} catch (ClientException $e) {
// Handle 4xx errors
} catch (ServerException $e) {
// Handle 5xx errors
}
Create middleware classes (e.g., for auth):
// src/Middleware/CustomAuthMiddleware.php
namespace App\Middleware;
use Guzzle\Common\Event;
use Guzzle\Common\Middleware;
class CustomAuthMiddleware implements Middleware
{
public function __invoke(Event $event)
{
$event['request']->setHeader('X-Auth-Token', 'your_token');
}
}
Register in config:
misd_guzzle:
clients:
default:
middleware:
- App\Middleware\CustomAuthMiddleware
Extend the base converter for custom logic:
// src/ParamConverter/CustomApiConverter.php
namespace App\ParamConverter;
use Misd\GuzzleBundle\ParamConverter\ApiConverter;
use Sensio\Bundle\FrameworkExtraBundle\Configuration\ParamConverter;
class CustomApiConverter extends ApiConverter
{
protected function getApiUrl($name, array $options)
{
return 'custom/' . parent::getApiUrl($name, $options);
}
}
Register as a service:
services:
app.param_converter.custom:
class: App\ParamConverter\CustomApiConverter
tags:
- { name: 'misd_guzzle.param_converter', alias: 'custom' }
Listen to Guzzle events (e.g., for analytics):
// src/EventSubscriber/GuzzleSubscriber.php
namespace App\EventSubscriber;
use Guzzle\Common\Event;
use Guzzle\Common
How can I help you explore Laravel packages today?