PHPackages                             phpexperts/simple-dto - 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. [API Development](/categories/api)
4. /
5. phpexperts/simple-dto

ActiveLibrary[API Development](/categories/api)

phpexperts/simple-dto
=====================

A quick and easy DTO package.

v3.9.1(1y ago)521.1M↓47.3%9[15 issues](https://github.com/phpexpertsinc/SimpleDTO/issues)7MITPHPPHP &gt;=7.4

Since Mar 29Pushed 1y ago2 watchersCompare

[ Source](https://github.com/phpexpertsinc/SimpleDTO)[ Packagist](https://packagist.org/packages/phpexperts/simple-dto)[ Docs](https://www.phpexperts.pro/)[ RSS](/packages/phpexperts-simple-dto/feed)WikiDiscussions master Synced 1mo ago

READMEChangelogDependencies (8)Versions (37)Used By (7)

SimpleDTO
=========

[](#simpledto)

[![TravisCI](https://camo.githubusercontent.com/789f3d87304ba87aef0cf08781f300a0f67d42b6a6c99b342e2053b27d826d85/68747470733a2f2f7472617669732d63692e636f6d2f70687065787065727473696e632f53696d706c6544544f2e7376673f6272616e63683d6d6173746572)](https://travis-ci.com/phpexpertsinc/SimpleDTO)[![Maintainability](https://camo.githubusercontent.com/a2a527d9a40c03717fe606aac46785e72d51763c51731c39dc5e4ab6cbda3e93/68747470733a2f2f6170692e636f6465636c696d6174652e636f6d2f76312f6261646765732f35303363626130633533656232363263393437612f6d61696e7461696e6162696c697479)](https://codeclimate.com/github/phpexpertsinc/SimpleDTO/maintainability)[![Test Coverage](https://camo.githubusercontent.com/54eaa7442ea0c2dc73862c27f6b580f29fbb89ce7c13b63004ade8fccb029a37/68747470733a2f2f6170692e636f6465636c696d6174652e636f6d2f76312f6261646765732f35303363626130633533656232363263393437612f746573745f636f766572616765)](https://codeclimate.com/github/phpexpertsinc/SimpleDTO/test_coverage)

SimpleDTO is a PHP Experts, Inc., Project meant to facilitate easy Data Transfer Objects.

Basically, any protected property on the DTO can be set as an array element passed in to the \_\_constructor and/or as a default value on the property itself.

The DTOs are immutable: Once created, they cannot be changed. Create a new object instead.

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

[](#installation)

Via Composer

```
composer require phpexperts/simple-dto
```

Usage
-----

[](#usage)

As of version 2, you *must* define class-level @property docblocks for each one of your properties.

You also must define the data type.

```
use Carbon\Carbon;
use PHPExperts\SimpleDTO\SimpleDTO;

/**
 * @property-read string $name
 * @property-read Carbon $date
 */
class BirthdayDTO extends SimpleDTO
{
    /** @var string */
    protected $name;

    /** @var Carbon */
    protected $date;
}

$birthdayDTO = new BirthdayDTO([
    'name' => 'Donald J. Trump',
    'date' => '1946-06-14',
]);

// Access as a property:
echo $birthday->name; // Donald J. Trump

// Properties with the data type of "Carbon" or "Carbon\Carbon"
// are automagically converted to Carbon objects.
echo $birthday->date->format('F jS, Y'); // June 14th, 1946

// Easily output as an array:
$birthday->toArray();

// Copy from one to another:
$newDTO = new BirthdayDTO($birthdayDTO->toArray());

// Copy from one to another, with new properties:
$newDTO = new BirthdayDTO($birthdayDTO->toArray() + [
    'date' => '2020-11-03',
]);

// Easily output as JSON:
echo json_encode($birthdayDTO);
/* Output:
{
    "name": "Donald J. Trump",
    "date": "1946-06-14T00:00:00.000000Z"
}
*/
```

### Fuzzy Data Types

[](#fuzzy-data-types)

But what if you aren't ready / able to dive into strict PHP data types yet?

Well, just instantiate the parent class like this:

```
    use PHPExperts\DataTypeValidator\DataTypeValidator;
    use PHPExperts\DataTypeValidator\IsAFuzzyDataType;

    /**
     * @property int   $daysAlive
     * @property float $age
     * @property bool  $isHappy
     */
    class MyFuzzyDTO extends SimpleDTO
    {
        public function __construct(array $input)
        {
            parent::__construct($input, new DataTypeValidator(new IsAFuzzyDataType());
        }
    }

    $person = new MyFuzzyDTO([
        'daysAlive' => '5000',
        'age'       => '13.689',
        'isHappy'   => 1,
    ]);

    echo json_encode($person, JSON_PRETTY_PRINT);
    /*
    {
        "daysAlive": "5000",
        "age": "13.689",
        "isHappy": 1
    }
    */
```

### WriteOnce DTOs

[](#writeonce-dtos)

Sometimes, you may need to initialize one or more values of a DTO after it has been created. This is particularly common for stateful DTOs via multiple round-trips in certain APIs (particularly Zuora's).

To overcome the stateless nature of traditional Data Type Objects, you can use the `WriteOnce` trait.

This will enable you to initialize a DTO with *null* and *uninitialized* properties, and set them *once* and only.

Also, you must set every property before you can serialize or `json_encode()` the object, send it to `toArray()`, etc.

```
/**
* @property string $name
*/
class CityDTO extends SimpleDTO
{
    use WriteOnce;

    protected int $population;
}

$cityDTO = new CityDTO(['name' => 'Dubai']);
dd($cityDTO);
```

### Ignore certain protected properties.

[](#ignore-certain-protected-properties)

If you are using PHP 8.0 and above, you can have SimpleDTO ignore any particular `protected` property (PHP will treat it like any regular protected property) using the `#[IgnoreAsDTO]` Attribute:

```
$testDTO = new class(['name' => 'Sofia', 'birthYear' => 2010]) extends SimpleDTO {
    #[IgnoreAsDTO]
    protected int $age;

    protected string $name;
    protected int $birthYear;

    public function calcAge(): int
    {
        $this->age = date('Y') - $this->birthYear;

        return $this->age;
    }
};
```

### NestedDTOs

[](#nesteddtos)

You can nest DTOs inside of each other.

```
    $myDTO = new MyTestDTO([
        'name' => 'PHP Experts, Inc.',
        'age'  => 7.01,
        'year' => 2019,
    ]);

    /**
     * @property MyTestDTO $myDTO
     */
    $dto = new class(['myDTO' => $myDTO]) extends NestedDTO
    {
    };

    /*
    PHPExperts\SimpleDTO\NestedDTO@anonymous {
      -dataTypeRules: array:1 [
        "myDTO" => "?MyTestDTO"
      ]
      -data: array:1 [
        "myDTO" => PHPExperts\SimpleDTO\Tests\MyTestDTO {#355
          -dataTypeRules: array:3 [
            "name" => "?string"
            "age" => "?float"
            "year" => "?int"
          ]
          -data: array:3 [
            "name" => "PHP Experts, Inc."
            "age" => 7.01
            "year" => 2019
          ]
        }
      ]
    }
    */
```

Use cases
=========

[](#use-cases)

PHPExperts\\SimpleDTO\\SimpleDTO
✔ Properties are set via the constructor
✔ Properties are accessed as public properties
✔ Constructor assigns default values of typed properties
✔ Public, private and static protected properties will be ignored
✔ Each DTO is immutable
✔ Setting any property returns an exception
✔ Concrete properties can be used to set default values
✔ Properties with the type carbon become carbon dates
✔ Can easily output to array
✔ Can easily be JSON encoded
✔ Can easily be JSON decoded
✔ Nullable properties are allowed
✔ Every property is nullable with permissive mode
✔ Can be serialized
✔ Can be unserialized
✔ Extra validation can be added
✔ Can get the internal data
✔ Can identify if it is permissive or not
✔ Can ignore protected properties with the #\[IgnoreDTO\] Attribute.

PHPExperts\\SimpleDTO\\NestedDTO
✔ Will construct nested DTOs
✔ Can construct arrays of nested DTOs
✔ Can retrieve the stored DTOs.
✔ Will convert array data into the appropriate Nested DTOs
✔ Will convert stdClasses into the appropriate Nested DTOs
✔ Nested DTOs use Loose typing
✔ Nested DTOs can be built using Typed Properties
✔ Nested DTOs with Typed Properties use Strict typing
✔ Nested DTOs with extra properties will work with Permissive mode
✔ All registered Nested DTOs are required
✔ Optional, unregistered, Nested DTOs are handled gracefully
✔ Can be serialized
✔ Can be unserialized
✔ Can validate the DTO manually
✔ Can get the internal data

PHPExperts\\SimpleDTO\\WriteOnceTrait
✔ Can accept null values
✔ Can be serialized
✔ Will validate on serialize
✔ Will validate on to array
✔ Can write each null value once
✔ Write-Once values must validate

SimpleDTO Sad Paths
✔ Cannot initialize with a nonexisting property
✔ Accessing a nonexisting property throws an error
✔ A DTO must have class property docblocks -or- typehint for each concrete property
✔ Carbon date strings must be parsable dates
✔ Properties must match their data types
✔ Will not unserialize DTOs with invalid data
✔ Cannot overwrite a non-existing property

Testing
-------

[](#testing)

```
phpunit --testdox
```

Contributors
============

[](#contributors)

[Theodore R. Smith](https://www.phpexperts.pro/%5D)
GPG Fingerprint: 4BF8 2613 1C34 87AC D28F 2AD8 EB24 A91D D612 5690
CEO: PHP Experts, Inc.

License
-------

[](#license)

MIT license. Please see the [license file](LICENSE) for more information.

###  Health Score

51

—

FairBetter than 96% of packages

Maintenance41

Moderate activity, may be stable

Popularity52

Moderate usage in the ecosystem

Community25

Small or concentrated contributor base

Maturity71

Established project with proven stability

 Bus Factor1

Top contributor holds 96.4% 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 ~63 days

Recently: every ~8 days

Total

36

Last Release

397d ago

Major Versions

v1.0.1 → v2.0.02019-05-13

v2.6.0 → v3.0.x-dev2023-05-19

v2.7.0 → v3.0.02023-05-19

PHP version history (3 changes)v1.0.0PHP &gt;=7.1

v2.5.0PHP &gt;=7.2

v3.6.x-devPHP &gt;=7.4

### Community

Maintainers

![](https://www.gravatar.com/avatar/3f3a2dd16766f6b03c330e65aaca9dfb97f1bbbb41c5e2af5681f58f670b7917?d=identicon)[hopeseekr](/maintainers/hopeseekr)

---

Top Contributors

[![hopeseekr](https://avatars.githubusercontent.com/u/1125541?v=4)](https://github.com/hopeseekr "hopeseekr (132 commits)")[![ametad](https://avatars.githubusercontent.com/u/1582541?v=4)](https://github.com/ametad "ametad (1 commits)")[![andrew-demb](https://avatars.githubusercontent.com/u/12499813?v=4)](https://github.com/andrew-demb "andrew-demb (1 commits)")[![apolitano1](https://avatars.githubusercontent.com/u/28787066?v=4)](https://github.com/apolitano1 "apolitano1 (1 commits)")[![peter279k](https://avatars.githubusercontent.com/u/9021747?v=4)](https://github.com/peter279k "peter279k (1 commits)")[![rpungello](https://avatars.githubusercontent.com/u/3287663?v=4)](https://github.com/rpungello "rpungello (1 commits)")

---

Tags

apirestfuldtodata transfer objects

###  Code Quality

TestsPHPUnit

Static AnalysisPHPStan

Code StylePHP\_CodeSniffer

Type Coverage Yes

### Embed Badge

![Health badge](/badges/phpexperts-simple-dto/health.svg)

```
[![Health](https://phpackages.com/badges/phpexperts-simple-dto/health.svg)](https://phpackages.com/packages/phpexperts-simple-dto)
```

###  Alternatives

[teepluss/api

Laravel 4 Internal Request (HMVC)

7034.0k](/packages/teepluss-api)[rekalogika/mapper

An object mapper for PHP and Symfony. Maps an object to another object. Primarily used for transforming an entity to a DTO and vice versa.

3847.7k1](/packages/rekalogika-mapper)

PHPackages © 2026

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