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)511.1M↓89.7%9[15 issues](https://github.com/phpexpertsinc/SimpleDTO/issues)7MITPHPPHP &gt;=7.4CI failing

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 2d 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

50

—

FairBetter than 95% of packages

Maintenance38

Infrequent updates — may be unmaintained

Popularity49

Moderate usage in the ecosystem

Community25

Small or concentrated contributor base

Maturity72

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

443d 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

[statamic/cms

The Statamic CMS Core Package

4.8k3.6M985](/packages/statamic-cms)[temporal/sdk

Temporal SDK

4072.9M25](/packages/temporal-sdk)[smodav/mpesa

M-Pesa API implementation

16467.9k1](/packages/smodav-mpesa)[teepluss/api

Laravel 4 Internal Request (HMVC)

7034.1k](/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.

3853.2k1](/packages/rekalogika-mapper)

PHPackages © 2026

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