PHPackages                             olivermack/duzzle - PHPackages - PHPackages  [Skip to content](#main-content)[PHPackages](/)[Directory](/)[Categories](/categories)[Trending](/trending)[Leaderboard](/leaderboard)[Changelog](/changelog)[Analyze](/analyze)[Collections](/collections)[Log in](/login)[Sign up](/register)

1. [Directory](/)
2. /
3. [HTTP &amp; Networking](/categories/http)
4. /
5. olivermack/duzzle

ActiveLibrary[HTTP &amp; Networking](/categories/http)

olivermack/duzzle
=================

Opinionated (thin) wrapper for Guzzle supporting request and response DTOs serialization with Symfony Serializer and Symfony Validator

0.1.0(1y ago)220MITPHPPHP ^8.3CI passing

Since Mar 2Pushed 8mo ago1 watchersCompare

[ Source](https://github.com/olivermack/duzzle)[ Packagist](https://packagist.org/packages/olivermack/duzzle)[ RSS](/packages/olivermack-duzzle/feed)WikiDiscussions main Synced 1mo ago

READMEChangelog (3)Dependencies (17)Versions (4)Used By (0)

Duzzle: An opinionated, DTO-centric Guzzle HTTP Wrapper
=======================================================

[](#duzzle-an-opinionated-dto-centric-guzzle-http-wrapper)

[![build](https://github.com/olivermack/duzzle/actions/workflows/quality.yml/badge.svg)](https://github.com/olivermack/duzzle/actions/workflows/quality.yml/badge.svg)[![codecov](https://camo.githubusercontent.com/24b8c630cb548326ecb5bead001b27d1f9b37bfba32010d6493979af4637ad3d/68747470733a2f2f636f6465636f762e696f2f6769746875622f6f6c697665726d61636b2f64757a7a6c652f67726170682f62616467652e7376673f746f6b656e3d5554434e325830525036)](https://codecov.io/github/olivermack/duzzle)

Duzzle (*[DTOs](https://en.wikipedia.org/wiki/Data_transfer_object) + [Guzzle](https://github.com/guzzle/guzzle)*) is a lightweight extension on top of Guzzle designed to seamlessly integrate DTO serialization and validation workflows into your HTTP client calls. It leverages the [Symfony Serializer](https://symfony.com/doc/current/serializer.html) and (optionally) the [Symfony Validator](https://symfony.com/doc/current/validation.html) to transform your domain objects (DTOs) into request payloads, validate them before dispatch, and then deserialize responses back into strongly typed objects—enabling a clean, high-level API around Guzzle's powerful HTTP capabilities.

If you’re seeking a straightforward, “DTO-first” approach to RESTful interactions without manually handling JSON or validation rules, Duzzle aims to provide an easy and extensible solution.

Installation
------------

[](#installation)

Install the package via composer

```
$ composer require olivermack/duzzle
```

Background
----------

[](#background)

Duzzle was created as a proof of concept to show how/if a single API client implementation can reduce complexity in a domain application which deals with multiple different remote APIs.

Because [Guzzle](https://github.com/guzzle/guzzle) is a pretty well known and widely used API client in the PHP world Duzzle was built as a "wrapper" for Guzzle right from the start - hence the weird name ;).

Duzzle works with `output` and `input` definitions for any particular API call.

In order to add an extra guard for the consumption of remote APIs, Duzzle allows the validation of the `input` before sending it to the remote API as well as validating the `output` of the API to ensure that the API-consumer can deal with unexpected changes or invalid data.

Usage
-----

[](#usage)

First, create an instance of `Duzzle` via the `DuzzleBuilder`:

```
$duzzle = DuzzleBuilder::create([
    // place your guzzle default options here
    'base_uri' => 'https://jsonplaceholder.typicode.com/',
])
    ->withDefaultSerializer()
    ->build();
```

With the instance you can perform your requests. To make the usage easier Duzzle only provides a single `request()` method, following the signature that Guzzle's `request()` provides.

To access the data which was handled by Duzzle's middlewares you need to call `getDuzzleResult()` on the response.

```
// without any further specification/configuration the client
// will automatically deserialize the resulting data as php array
$result = $duzzle->request('GET', '/todos/1')->getDuzzleResult();

/**
 * array(4) {
 *   'userId' => int(1)
 *   'id' => int(1)
 *   'title' => string(18) "delectus aut autem"
 *   'completed' => bool(false)
 * }
 */
```

### DTO (De)Serialization

[](#dto-deserialization)

To deserialize the response into your domain specific DTO, you need to define the class as POPO (*plain old php object*) and tell the client to use it as `output` type:

```
class Todo
{
    public ?int $id = null;
    public int $userId;
    public string $title;
    public bool $completed;
}

$result = $duzzle->request('GET', '/todos/1', [
    DuzzleOptionsKeys::OUTPUT => Todo::class
    // or
    'output' => Todo::class,
])->getDuzzleResult();

/**
 * class Todo#159 (4) {
 *   public ?int $id => int(1)
 *   public int $userId => int(1)
 *   public string $title => string(18) "delectus aut autem"
 *   public bool $completed => bool(false)
 * }
 */
```

To send an instance of a DTO to the API, you need to provide the instance as `input`:

```
$newTodo = new Todo();
$newTodo->userId = 1;
$newTodo->completed = true;
$newTodo->title = 'My new task!';

$createdTodoResult = $duzzle->request('POST', '/todos', [
    DuzzleOptionsKeys::INPUT => $newTodo,
    // if we don't provide an output DTO we'll get the result as array!
    DuzzleOptionsKeys::OUTPUT => Todo::class,
]);
```

#### Custom Serializer

[](#custom-serializer)

The default serializer setup shipped with Duzzle is configured for the most common JSON API examples. However, if you need to use your own serializer stack you can provide it in the builder:

```
// define your serializer
$serializer = new \Symfony\Component\Serializer\Serializer();
// pass it to the builder
$duzzle = DuzzleBuilder::create($options)
    ->withSerializer($serializer)
    ->build();
```

### Validation

[](#validation)

To use the (optional) validation capabilities you need to install the required `symfony/validator` package.

```
$ composer req symfony/validator
```

Now, when you create your `Duzzle` instance, you can ask the builder to set up the default validation behavior for you.

#### Validation Strategies

[](#validation-strategies)

Duzzle works with different "Strategies" to determine how the validation result should affect the behavior of the API client.

> ℹ️ **Without specifying a strategy, no validation will actually happen** even if you told the builder to use the default validator!

```
$duzzle = DuzzleBuilder::create([
    DuzzleOptionsKeys::INPUT_VALIDATION => DefaultStrategyKey::BLOCKING->value,
    // same as:
    'input_validation' => 'blocking',

    DuzzleOptionsKeys::OUTPUT_VALIDATION => DefaultStrategyKey::BLOCKING->value,
    // same as:
    'output_validation' => 'blocking',

    // ...other options
])
    ->withDefaultSerializer()
    ->withDefaultValidator()
    ->build();
```

The following strategies are shipped with Duzzle:

- `DefaultStrategyKey::NOOP` / ``noop` - does not do anything with the results but enables the validation
- `DefaultStrategyKey::INFORMATIVE` / `informative` - allows you to log validation results
- `DefaultStrategyKey::BLOCKING` / `blocking` - throws an exception when the input or output payload are considered invalid

The `informative` strategy expects a [PSR-3 logger](https://www.php-fig.org/psr/psr-3/). You need to pass one in the builder to get any effective output using `$builder->withLogger($myLogger)`.

#### Validation constraints

[](#validation-constraints)

With the default validator defined you can use PHP attributes to define your rules on the DTO class:

```
use Symfony\Component\Validator\Constraints as Assert;

class Todo
{
    public ?int $id = null;
    #[Assert\Positive]
    public int $userId;
    #[Assert\NotBlank]
    #[Assert\Length(min: 1, max: 255)]
    public string $title;
    public bool $completed;
}
```

To validate the input, make sure your Duzzle instance is equipped with a default `input_validation` or define it per request like so:

```
$todo = new Todo();
$duzzle->request('POST', '/todos', [
    'input' => $todo,
    'input_validation' => 'blocking',
])->getDuzzleResult();
```

> For a working example check out `examples/02-validation-json-api.php`

Todos
-----

[](#todos)

- dev ecosystem
- lib builder / factories
- most crucial code quality tooling
- DTO (de)serialization
    - dealing with JSON API output
    - dealing with JSON API input
    - dealing with XML API output
    - dealing with XML API input
- DTO validation
    - validating output DTOs
    - validating input DTOs

###  Health Score

31

—

LowBetter than 68% of packages

Maintenance53

Moderate activity, may be stable

Popularity9

Limited adoption so far

Community9

Small or concentrated contributor base

Maturity45

Maturing project, gaining track record

 Bus Factor1

Top contributor holds 66.7% of commits — single point of failure

How is this calculated?**Maintenance (25%)** — Last commit recency, latest release date, and issue-to-star ratio. Uses a 2-year decay window.

**Popularity (30%)** — Total and monthly downloads, GitHub stars, and forks. Logarithmic scaling prevents top-heavy scores.

**Community (15%)** — Contributors, dependents, forks, watchers, and maintainers. Measures real ecosystem engagement.

**Maturity (30%)** — Project age, version count, PHP version support, and release stability.

###  Release Activity

Cadence

Every ~4 days

Total

3

Last Release

432d ago

### Community

Maintainers

![](https://www.gravatar.com/avatar/052257ea2dfc5a9e83fb33540787158c2b75b912a8d38809d6f2dd0f09f61213?d=identicon)[olivermack](/maintainers/olivermack)

---

Top Contributors

[![omack](https://avatars.githubusercontent.com/u/1389984?v=4)](https://github.com/omack "omack (14 commits)")[![olivermack](https://avatars.githubusercontent.com/u/666035?v=4)](https://github.com/olivermack "olivermack (7 commits)")

---

Tags

dtoguzzleguzzle-middlewarehttp-clientsymfony-serializersymfony-validator

###  Code Quality

TestsPest

Static AnalysisPHPStan

Code StylePHP CS Fixer

Type Coverage Yes

### Embed Badge

![Health badge](/badges/olivermack-duzzle/health.svg)

```
[![Health](https://phpackages.com/badges/olivermack-duzzle/health.svg)](https://phpackages.com/packages/olivermack-duzzle)
```

###  Alternatives

[sylius/sylius

E-Commerce platform for PHP, based on Symfony framework.

8.4k5.6M651](/packages/sylius-sylius)[nelmio/api-doc-bundle

Generates documentation for your REST API from attributes

2.3k63.6M233](/packages/nelmio-api-doc-bundle)[craftcms/cms

Craft CMS

3.6k3.6M2.6k](/packages/craftcms-cms)[symfony/serializer-pack

A pack for the Symfony serializer

1.1k28.2M221](/packages/symfony-serializer-pack)[shopware/platform

The Shopware e-commerce core

3.3k1.5M3](/packages/shopware-platform)[api-platform/symfony

Symfony API Platform integration

323.2M67](/packages/api-platform-symfony)

PHPackages © 2026

[Directory](/)[Categories](/categories)[Trending](/trending)[Changelog](/changelog)[Analyze](/analyze)
