PHPackages                             tuxonice/transfer-objects - 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. [Utility &amp; Helpers](/categories/utility)
4. /
5. tuxonice/transfer-objects

ActiveLibrary[Utility &amp; Helpers](/categories/utility)

tuxonice/transfer-objects
=========================

Build data transfer objects from json definition

v1.1.2(2y ago)315.0k↑53.3%[1 issues](https://github.com/tuxonice/data-transfer-object/issues)MITPHPPHP ^8.0CI passing

Since Sep 30Pushed 1w ago1 watchersCompare

[ Source](https://github.com/tuxonice/data-transfer-object)[ Packagist](https://packagist.org/packages/tuxonice/transfer-objects)[ RSS](/packages/tuxonice-transfer-objects/feed)WikiDiscussions main Synced 2w ago

READMEChangelog (10)Dependencies (6)Versions (16)Used By (0)

Bare simple data transfer object
================================

[](#bare-simple-data-transfer-object)

[![Build Status](https://github.com/tuxonice/data-transfer-object/actions/workflows/pipeline.yml/badge.svg)](https://github.com/tuxonice/data-transfer-object/actions)[![Total Downloads](https://camo.githubusercontent.com/f33c720df0ad4a30b83e3b428d465cb012c5ee13f723658560a43db8babf1560/68747470733a2f2f696d672e736869656c64732e696f2f7061636b61676973742f64742f7475786f6e6963652f7472616e736665722d6f626a65637473)](https://packagist.org/packages/tuxonice/transfer-objects)[![Latest Stable Version](https://camo.githubusercontent.com/cb73d3c6f53fc4797139deb5df9584be40c00a99eff940f58f30eea500013caa/68747470733a2f2f696d672e736869656c64732e696f2f6769746875622f762f72656c656173652f7475786f6e6963652f646174612d7472616e736665722d6f626a656374)](https://packagist.org/packages/tuxonice/transfer-objects)[![License](https://camo.githubusercontent.com/c85e2e6982fa7959f79c16784e640d601a6635edae884b07900e63c2768f799e/68747470733a2f2f696d672e736869656c64732e696f2f7061636b61676973742f6c2f7475786f6e6963652f7472616e736665722d6f626a65637473)](https://packagist.org/packages/tuxonice/transfer-objects)

In the ever-evolving landscape of software development, efficient and structured data communication is paramount. DTO package is designed to streamline and enhance the way data is transferred between different layers of your application, promoting clarity, maintainability, and robustness.

Whether you're building a RESTful API, a microservices architecture, or a traditional web application, Data Transfer Objects package empowers you to manage data flow with elegance and precision. Elevate your code quality and simplify your data handling processes with our intuitive and developer-friendly DTO solution.

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

[](#installation)

You can install the package via composer:

```
composer require tuxonice/transfer-objects
```

Setup
-----

[](#setup)

The goal of this package is to create data transfer objects from json definitions as easy as possible.

1. In your project create a folder to hold on the definition files.

```
mkdir "src/dto-definitions"
```

2. Create a folder to hold on the generated data transfer objects

```
mkdir "src/DataTransferObjects"
```

3. Create a command to generate the DTO's. If you are using symfony console could be something like:

```
namespace Acme\Command;

use Symfony\Component\Console\Command\Command;
use Symfony\Component\Console\Input\InputInterface;
use Symfony\Component\Console\Output\OutputInterface;
use Tlab\TransferObjects\DataTransferBuilder;

class GenerateTransferCommand extends Command
{
    protected static $defaultName = 'transfer:generate';

    protected function configure(): void
    {
        $this
            ->setDescription('Generate transfer objects')
            ->setHelp('Generate transfer objects');
    }

    protected function execute(InputInterface $input, OutputInterface $output): int
    {
        $dataTransferBuilder = new DataTransferBuilder(
            dirname(__DIR__) . '/dto-definitions/',
            dirname(__DIR__) . '/DataTransferObjects/',
            'Acme\\DataTransferObjects',
        );
        $dataTransferBuilder->build();

        return Command::SUCCESS;
    }
}
```

4. For Laravel projects:

```
php artisan make:command GenerateTransfer
```

```

namespace App\Console\Commands;

use Illuminate\Console\Command;
use Tlab\TransferObjects\DataTransferBuilder;

class GenerateTransfer extends Command
{
    /**
     * The name and signature of the console command.
     *
     * @var string
     */
    protected $signature = 'transfer:generate';

    /**
     * The console command description.
     *
     * @var string
     */
    protected $description = 'Generate data transfer objects';

    /**
     * Execute the console command.
     */
    public function handle(): void
    {
        $dataTransferBuilder = new DataTransferBuilder(
            dirname(__DIR__) . '/dto-definitions/',
            dirname(__DIR__) . '/DataTransferObjects/',
            'Acme\\DataTransferObjects',
        );
        $dataTransferBuilder->build();
    }
}
```

5. Define the dto through the definition file

`src/dto-definitions/customer.json`

```
{
  "transfers": [
    {
      "name": "Customer",
      "properties": [
        {
          "name": "firstName",
          "type": "string"
        },
        {
          "name": "lastName",
          "type": "string",
          "nullable": true
        },
        {
          "name": "email",
          "type": "string",
          "nullable": false
        },
        {
          "name": "birthDate",
          "type": "DateTime",
          "namespace": "DateTime"
        },
        {
          "name": "isActive",
          "type": "bool"
        }
      ]
    }
  ]
}
```

This definition will generate the following transfer class:

```
namespace Acme\DataTransferObjects;

use DateTime;
use Tlab\TransferObjects\AbstractTransfer;

/**
 * !!! THIS TRANSFER CLASS FILE IS AUTO-GENERATED, CHANGES WILL BREAK YOUR PROJECT
 * !!! DO NOT CHANGE ANYTHING IN THIS FILE
 */
class CustomerTransfer extends AbstractTransfer
{
    /**
     * @var string
     */
    private string $firstName;

    /**
     * @var string|null
     */
    private ?string $lastName;

    /**
     * @var string
     */
    private string $email;

    /**
     * @var DateTime
     */
    private DateTime $birthDate;

    /**
     * @var bool
     */
    private bool $isActive;

    /**
     * @return string
     */
    public function getFirstName(): string
    {
        return $this->firstName;
    }

    /**
     * @param string $firstName
     *
     * @return $this
     */
    public function setFirstName(string $firstName): self
    {
        $this->firstName = $firstName;

        return $this;
    }

    /**
     * @return string|null
     */
    public function getLastName(): ?string
    {
        return $this->lastName;
    }

    /**
     * @param string|null $lastName
     *
     * @return $this
     */
    public function setLastName(?string $lastName): self
    {
        $this->lastName = $lastName;

        return $this;
    }

    /**
     * @return string
     */
    public function getEmail(): string
    {
        return $this->email;
    }

    /**
     * @param string $email
     *
     * @return $this
     */
    public function setEmail(string $email): self
    {
        $this->email = $email;

        return $this;
    }

    /**
     * @return DateTime
     */
    public function getBirthDate(): DateTime
    {
        return $this->birthDate;
    }

    /**
     * @param DateTime $birthDate
     *
     * @return $this
     */
    public function setBirthDate(DateTime $birthDate): self
    {
        $this->birthDate = $birthDate;

        return $this;
    }

    /**
     * @return bool
     */
    public function getIsActive(): bool
    {
        return $this->isActive;
    }

    /**
     * @param bool $isActive
     *
     * @return $this
     */
    public function setIsActive(bool $isActive): self
    {
        $this->isActive = $isActive;

        return $this;
    }
}
```

Usage
-----

[](#usage)

### Creating and set data

[](#creating-and-set-data)

```
$customerTransfer = new CustomerTransfer();
$customerTransfer
    ->setFirstName('John')
    ->setLastName('Smith')
    ->setEmail('user@example.com')
    ->setBirthDate(new DateTime('2000-01-01'))
    ->setIsActive(true);
```

### Get data

[](#get-data)

```
$firstName = $customerTransfer->getFirstName(); // John
$lastName = $customerTransfer->getLastName(); // Smith
```

### Creating from array

[](#creating-from-array)

When creating from array its possible to use both **camelCase** or **snake\_case** as array keys

```
$data = [
    'first_name' => 'John',
    'last_name' => 'Smith',
    'email' => 'user@example.com',
    'birth_date' => new DateTime('2000-01-01'),
    'is_active' => true),
];
$customerTransfer = CustomerTransfer::fromArray($data);

$data = [
    'streetName' => 'test street name',
    'city' => 'test-city',
    'zipCode' => '1999',
    'isDefaultBillingAddress' => true,
    'isDefaultShippingAddress' => false,
];
$addressTransfer = AddressTransfer::fromArray($data);
```

### Export to array

[](#export-to-array)

```
$customerTransfer = new CustomerTransfer();
$customerTransfer
    ->setFirstName('John')
    ->setLastName('Smith')
    ->setEmail('user@example.com')
    ->setBirthDate(new DateTime('2000-01-01'))
    ->setIsActive(true);

$data = $customerTransfer->toArray();
```

will return:

```
[
    'firstName' => 'John',
    'lastName' => 'Smith',
    'email' => 'user@example.com',
    'birthDate' => new DateTime('2000-01-01'),
    'isActive' => true,
]
```

The `toArray()` method has two parameters

```
public function toArray(bool $isRecursive = false, bool $snakeCaseKeys = false): array
```

- `isRecursive` when true will also export child transfer objects to an array

```
$customerTransfer = new CustomerTransfer();
$customerTransfer
    ->setEmail('user@example.com')
    ->setBirthDate(new DateTime('2000-01-01'))
    ->setFirstName('John')
    ->setLastName('Smith')
    ->setIsActive(true);

$orderItemTransfer1 = new OrderItemTransfer();
$orderItemTransfer1
    ->setName('Chips')
    ->setPrice(5.99)
    ->setQuantity(1)
    ->setId(1);

$orderItemTransfer2 = new OrderItemTransfer();
$orderItemTransfer2
    ->setName('Juice')
    ->setPrice(3.45)
    ->setQuantity(2)
    ->setId(2);

$orderTransfer = new OrderTransfer();
$orderTransfer
    ->setId(1)
    ->setCustomer($customerTransfer)
    ->setTotal(10.00)
    ->setOrderItems([
        $orderItemTransfer1,
        $orderItemTransfer2
    ])
    ->setCreatedAt(new DateTime('2023-10-01'));

$data = $orderTransfer->toArray(true);
```

will return:

```
[
    'id' => 1,
    'customer' => [
        'firstName' => 'John',
        'lastName' => 'Smith',
        'email' => 'user@example.com',
        'birthDate' => new DateTime('2000-01-01'),
        'isActive' => true,
    ],
    'total' => 10.0,
    'orderItems' => [
        [
            'id' => 1,
            'name' => 'Chips',
            'price' => 5.99,
            'quantity' => 1,
        ],
        [
            'id' => 2,
            'name' => 'Juice',
            'price' => 3.45,
            'quantity' => 2,
        ],
    ],
    'createdAt' => new DateTime('2023-10-01'),
]
```

- `snakeCaseKeys` when true will also export array with *snake\_case* keys (by default is *camelCase*)

```
$customerTransfer = new CustomerTransfer();
$customerTransfer
    ->setFirstName('John')
    ->setLastName('Smith')
    ->setEmail('user@example.com')
    ->setBirthDate(new DateTime('2000-01-01'))
    ->setIsActive(true);

$data = $customerTransfer->toArray(false, true);
```

will return:

```
[
    'first_name' => 'John',
    'last_name' => 'Smith',
    'email' => 'user@example.com',
    'birth_date' => new DateTime('2000-01-01'),
    'is_active' => true,
]
```

Create definition file(s)
-------------------------

[](#create-definition-files)

You can define one or more transfer objects definitions for each json file. Start by creating a json object that will contain your definitions:

```
{
  "transfers": [
  ]
}
```

and inside the `transfers` array define your transfer:

```
{
  "name": "Customer",
  "properties": [
    {
      "name": "firstName",
      "type": "string"
    },
    {
      "name": "lastName",
      "type": "string"
    },
    {
      "name": "isActive",
      "type": "bool"
    }
  ]
}
```

### Available fields

[](#available-fields)

- Class

FieldTypeRequiredDefaultDescriptionnamestringyes--The transfer object name. The result class name will be this name concatenated with "Transfer". E.g. CustomerTransferpropertiesarrayyes--An array of objects with definition of each class propertyimmutableboolnofalseRemove setters from the class. In this case the class name will end with "TransferImmutable"deprecationDescriptionstringno""If present and not empty, will add an annotation with @deprecated, to mark this class as deprecated- Class properties

FieldTypeRequiredDefaultDescriptionnamestringyes--field name in camelCasetypestringyes--The field type. Can be a native type (string, int, float, bool), `array`, or any other class. If the type ends with \[\], will mark the property as a typed arraydeprecationDescriptionstringno""If present and with a text, will add an annotation with @deprecated, to mark this field as deprecatednullableboolnofalseSet if the property can be null. Can not be set to true for a typed array (a type ending in \[\]), but is allowed for a plain `array`namespacestringyes if the type is another class--Namespace for the class in case the property type is another class (except another transfer object)singularstringyes if the type is a typed array--Singular form of the property, used to name the "add" method. Only applies to types ending in \[\]### Example of property definitions

[](#example-of-property-definitions)

- integer

```
{
  "name": "id",
  "type": "int"
}
```

- nullable string

```
{
  "name": "firstName",
  "type": "string",
  "nullable": true
}
```

- another transfer object as property

```
{
  "name": "customer",
  "type": "CustomerTransfer"
}
```

- DateTime property

```
{
  "name": "createdAt",
  "type": "DateTime",
  "namespace": "DateTime"
}
```

- Array of strings

```
{
  "name": "tags",
  "type": "string[]",
  "singular": "tag"
}
```

- Array of transfer objects

```
{
  "name": "categories",
  "type": "CategoryTransfer[]",
  "singular": "category"
}
```

- Plain array, for a structure with no single element type

```
{
  "name": "meta",
  "type": "array"
}
```

Documented as `array` and defaulting to `[]`. No `singular` is needed and no `add` method is generated, since there is no element type to name one after. Unlike a typed array, a plain `array` may be `nullable`, in which case it defaults to `null` instead:

```
{
  "name": "payload",
  "type": "array",
  "nullable": true
}
```

- Symfony Response

```
{
  "name": "response",
  "type": "Response",
  "namespace": "\\Symfony\\Component\\HttpFoundation\\Response"
}
```

Contributing
------------

[](#contributing)

The test suite runs in Docker, on the same PHP version the CI pipeline uses, with [PCOV](https://github.com/krakjoe/pcov) available for code coverage. Build the image once:

```
make build
make install
```

Then:

CommandDescription`make test`Run the test suite`make coverage`Run the test suite and write an HTML report to `coverage/``make phpcs`Check the code style`make phpstan`Run static analysis`make ci`Run the full pipeline, as CI does`make shell`Open a shell in the containerRun `make` on its own to list the available targets.

License
-------

[](#license)

The MIT License (MIT). Please see [License File](LICENSE.md) for more information.

###  Health Score

41

—

FairBetter than 87% of packages

Maintenance57

Moderate activity, may be stable

Popularity29

Limited adoption so far

Community9

Small or concentrated contributor base

Maturity57

Maturing project, gaining track record

 Bus Factor1

Top contributor holds 68.6% 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 ~14 days

Recently: every ~24 days

Total

14

Last Release

865d ago

Major Versions

v0.3.3 → v1.0.02023-12-29

PHP version history (2 changes)v0.1.0PHP ^8.2

v1.1.1PHP ^8.0

### Community

Maintainers

![](https://avatars.githubusercontent.com/u/916066?v=4)[Helder Correia](/maintainers/tuxonice)[@tuxonice](https://github.com/tuxonice)

---

Top Contributors

[![tuxonice](https://avatars.githubusercontent.com/u/916066?v=4)](https://github.com/tuxonice "tuxonice (35 commits)")[![renovate[bot]](https://avatars.githubusercontent.com/in/2740?v=4)](https://github.com/renovate[bot] "renovate[bot] (16 commits)")

---

Tags

dtodata transfer objects

###  Code Quality

TestsPHPUnit

Static AnalysisPHPStan

Code StylePHP\_CodeSniffer

Type Coverage Yes

### Embed Badge

![Health badge](/badges/tuxonice-transfer-objects/health.svg)

```
[![Health](https://phpackages.com/badges/tuxonice-transfer-objects/health.svg)](https://phpackages.com/packages/tuxonice-transfer-objects)
```

###  Alternatives

[friendsoftypo3/content-blocks

TYPO3 CMS Content Blocks - Content Types API | Define reusable components via YAML

103574.3k69](/packages/friendsoftypo3-content-blocks)[cpsit/project-builder

Composer package to create new projects from project templates

2640.2k5](/packages/cpsit-project-builder)[php-collective/dto

Framework-agnostic Data Transfer Object library with code generation

3015.7k7](/packages/php-collective-dto)

PHPackages © 2026

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