{"id":20737096,"url":"https://github.com/phpexpertsinc/simpledto","last_synced_at":"2025-04-13T11:47:43.001Z","repository":{"id":34388351,"uuid":"178183652","full_name":"PHPExpertsInc/SimpleDTO","owner":"PHPExpertsInc","description":"An easy-to-use generic DTO package for PHP.","archived":false,"fork":false,"pushed_at":"2025-03-18T03:37:03.000Z","size":237,"stargazers_count":50,"open_issues_count":0,"forks_count":11,"subscribers_count":2,"default_branch":"master","last_synced_at":"2025-04-06T07:06:01.666Z","etag":null,"topics":[],"latest_commit_sha":null,"homepage":null,"language":"PHP","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/PHPExpertsInc.png","metadata":{"files":{"readme":"README.md","changelog":"CHANGELOG.md","contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null}},"created_at":"2019-03-28T10:48:49.000Z","updated_at":"2025-03-18T03:35:21.000Z","dependencies_parsed_at":"2024-07-30T23:33:03.462Z","dependency_job_id":null,"html_url":"https://github.com/PHPExpertsInc/SimpleDTO","commit_stats":{"total_commits":68,"total_committers":6,"mean_commits":"11.333333333333334","dds":0.07352941176470584,"last_synced_commit":"7da14977fdc645cf2bf5fd006a515e6ac8d840b5"},"previous_names":[],"tags_count":25,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/PHPExpertsInc%2FSimpleDTO","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/PHPExpertsInc%2FSimpleDTO/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/PHPExpertsInc%2FSimpleDTO/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/PHPExpertsInc%2FSimpleDTO/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/PHPExpertsInc","download_url":"https://codeload.github.com/PHPExpertsInc/SimpleDTO/tar.gz/refs/heads/master","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":248710409,"owners_count":21149186,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":[],"created_at":"2024-11-17T06:13:32.804Z","updated_at":"2025-04-13T11:47:42.979Z","avatar_url":"https://github.com/PHPExpertsInc.png","language":"PHP","funding_links":[],"categories":[],"sub_categories":[],"readme":"# SimpleDTO\n\n[![TravisCI](https://travis-ci.com/phpexpertsinc/SimpleDTO.svg?branch=master)](https://travis-ci.com/phpexpertsinc/SimpleDTO)\n[![Maintainability](https://api.codeclimate.com/v1/badges/503cba0c53eb262c947a/maintainability)](https://codeclimate.com/github/phpexpertsinc/SimpleDTO/maintainability)\n[![Test Coverage](https://api.codeclimate.com/v1/badges/503cba0c53eb262c947a/test_coverage)](https://codeclimate.com/github/phpexpertsinc/SimpleDTO/test_coverage)\n\nSimpleDTO is a PHP Experts, Inc., Project meant to facilitate easy Data Transfer Objects.\n\nBasically, any protected property on the DTO can be set as an array element passed in to\nthe __constructor and/or as a default value on the property itself.\n\nThe DTOs are immutable: Once created, they cannot be changed. Create a new object instead.\n\n## Installation\n\nVia Composer\n\n```bash\ncomposer require phpexperts/simple-dto\n```\n\n## Usage\n\nAs of version 2, you *must* define class-level @property docblocks for each one of your properties.\n\nYou also must define the data type.\n\n```php\nuse Carbon\\Carbon;\nuse PHPExperts\\SimpleDTO\\SimpleDTO;\n\n/**\n * @property-read string $name\n * @property-read Carbon $date\n */\nclass BirthdayDTO extends SimpleDTO\n{\n    /** @var string */\n    protected $name;\n    \n    /** @var Carbon */\n    protected $date;\n}\n\n$birthdayDTO = new BirthdayDTO([\n    'name' =\u003e 'Donald J. Trump',\n    'date' =\u003e '1946-06-14',\n]);\n\n// Access as a property:\necho $birthday-\u003ename; // Donald J. Trump\n\n// Properties with the data type of \"Carbon\" or \"Carbon\\Carbon\" \n// are automagically converted to Carbon objects.\necho $birthday-\u003edate-\u003eformat('F jS, Y'); // June 14th, 1946\n\n// Easily output as an array:\n$birthday-\u003etoArray();\n\n// Copy from one to another:\n$newDTO = new BirthdayDTO($birthdayDTO-\u003etoArray());\n\n// Copy from one to another, with new properties:\n$newDTO = new BirthdayDTO($birthdayDTO-\u003etoArray() + [\n    'date' =\u003e '2020-11-03',\n]);\n\n// Easily output as JSON:\necho json_encode($birthdayDTO);\n/* Output: \n{\n    \"name\": \"Donald J. Trump\",\n    \"date\": \"1946-06-14T00:00:00.000000Z\"\n}\n*/\n```\n\n### Fuzzy Data Types\n\nBut what if you aren't ready / able to dive into strict PHP data types yet?\n\nWell, just instantiate the parent class like this:\n\n```php\n    use PHPExperts\\DataTypeValidator\\DataTypeValidator;\n    use PHPExperts\\DataTypeValidator\\IsAFuzzyDataType;\n    \n    /**\n     * @property int   $daysAlive\n     * @property float $age\n     * @property bool  $isHappy\n     */\n    class MyFuzzyDTO extends SimpleDTO\n    {\n        public function __construct(array $input)\n        {\n            parent::__construct($input, new DataTypeValidator(new IsAFuzzyDataType());\n        }\n    }\n\n    $person = new MyFuzzyDTO([\n        'daysAlive' =\u003e '5000',\n        'age'       =\u003e '13.689',\n        'isHappy'   =\u003e 1,\n    ]);\n\n    echo json_encode($person, JSON_PRETTY_PRINT);\n    /*\n    {\n        \"daysAlive\": \"5000\",\n        \"age\": \"13.689\",\n        \"isHappy\": 1\n    }\n    */\n```\n\n### WriteOnce DTOs\n\nSometimes, you may need to initialize one or more values of a DTO after it has been created. This is particularly\ncommon for stateful DTOs via multiple round-trips in certain APIs (particularly Zuora's).\n\nTo overcome the stateless nature of traditional Data Type Objects, you can use the `WriteOnce` trait.\n\nThis will enable you to initialize a DTO with *null* and *uninitialized* properties, and set them *once* and only.\n\nAlso, you must set every property before you can serialize or `json_encode()` the object, send it to `toArray()`, etc.\n\n```php\n/**\n* @property string $name\n*/\nclass CityDTO extends SimpleDTO\n{\n    use WriteOnce;\n\n    protected int $population;\n}\n\n$cityDTO = new CityDTO(['name' =\u003e 'Dubai']);\ndd($cityDTO);\n```\n\n### Ignore certain protected properties.\n\nIf you are using PHP 8.0 and above, you can have SimpleDTO ignore any particular `protected` property (PHP will treat it\nlike any regular protected property) using the `#[IgnoreAsDTO]` Attribute:\n\n```php\n$testDTO = new class(['name' =\u003e 'Sofia', 'birthYear' =\u003e 2010]) extends SimpleDTO {\n    #[IgnoreAsDTO]\n    protected int $age;\n\n    protected string $name;\n    protected int $birthYear;\n\n    public function calcAge(): int\n    {\n        $this-\u003eage = date('Y') - $this-\u003ebirthYear;\n\n        return $this-\u003eage;\n    }\n};\n```\n\n### NestedDTOs\n\nYou can nest DTOs inside of each other. \n\n```php\n    $myDTO = new MyTestDTO([\n        'name' =\u003e 'PHP Experts, Inc.',\n        'age'  =\u003e 7.01,\n        'year' =\u003e 2019,\n    ]);\n\n    /**\n     * @property MyTestDTO $myDTO\n     */\n    $dto = new class(['myDTO' =\u003e $myDTO]) extends NestedDTO\n    {\n    };\n    \n    /*\n    PHPExperts\\SimpleDTO\\NestedDTO@anonymous {\n      -dataTypeRules: array:1 [\n        \"myDTO\" =\u003e \"?MyTestDTO\"\n      ]\n      -data: array:1 [\n        \"myDTO\" =\u003e PHPExperts\\SimpleDTO\\Tests\\MyTestDTO {#355\n          -dataTypeRules: array:3 [\n            \"name\" =\u003e \"?string\"\n            \"age\" =\u003e \"?float\"\n            \"year\" =\u003e \"?int\"\n          ]\n          -data: array:3 [\n            \"name\" =\u003e \"PHP Experts, Inc.\"\n            \"age\" =\u003e 7.01\n            \"year\" =\u003e 2019\n          ]\n        }\n      ]\n    }\n    */\n```\n\n# Use cases\nPHPExperts\\SimpleDTO\\SimpleDTO  \n ✔ Properties are set via the constructor  \n ✔ Properties are accessed as public properties  \n ✔ Constructor assigns default values of typed properties  \n ✔ Public, private and static protected properties will be ignored  \n ✔ Each DTO is immutable  \n ✔ Setting any property returns an exception  \n ✔ Concrete properties can be used to set default values  \n ✔ Properties with the type carbon become carbon dates  \n ✔ Can easily output to array  \n ✔ Can easily be JSON encoded  \n ✔ Can easily be JSON decoded  \n ✔ Nullable properties are allowed  \n ✔ Every property is nullable with permissive mode  \n ✔ Can be serialized  \n ✔ Can be unserialized  \n ✔ Extra validation can be added  \n ✔ Can get the internal data  \n ✔ Can identify if it is permissive or not  \n ✔ Can ignore protected properties with the #[IgnoreDTO] Attribute.\n\nPHPExperts\\SimpleDTO\\NestedDTO  \n ✔ Will construct nested DTOs  \n ✔ Can construct arrays of nested DTOs  \n ✔ Can retrieve the stored DTOs.  \n ✔ Will convert array data into the appropriate Nested DTOs  \n ✔ Will convert stdClasses into the appropriate Nested DTOs  \n ✔ Nested DTOs use Loose typing  \n ✔ Nested DTOs can be built using Typed Properties  \n ✔ Nested DTOs with Typed Properties use Strict typing  \n ✔ All registered Nested DTOs are required  \n ✔ Optional, unregistered, Nested DTOs are handled gracefully  \n ✔ Can be serialized  \n ✔ Can be unserialized  \n ✔ Can validate the DTO manually  \n ✔ Can get the internal data\n\nPHPExperts\\SimpleDTO\\WriteOnceTrait  \n ✔ Can accept null values  \n ✔ Can be serialized  \n ✔ Will validate on serialize  \n ✔ Will validate on to array  \n ✔ Can write each null value once  \n ✔ Write-Once values must validate  \n\nSimpleDTO Sad Paths  \n ✔ Cannot initialize with a nonexisting property  \n ✔ Accessing a nonexisting property throws an error  \n ✔ A DTO must have class property docblocks -or- typehint for each concrete property  \n ✔ Carbon date strings must be parsable dates  \n ✔ Properties must match their data types  \n ✔ Will not unserialize DTOs with invalid data  \n ✔ Cannot overwrite a non-existing property  \n\n## Testing\n\n```bash\nphpunit --testdox\n```\n\n# Contributors\n\n[Theodore R. Smith](https://www.phpexperts.pro/]) \u003ctheodore@phpexperts.pro\u003e  \nGPG Fingerprint: 4BF8 2613 1C34 87AC D28F  2AD8 EB24 A91D D612 5690  \nCEO: PHP Experts, Inc.\n\n## License\n\nMIT license. Please see the [license file](LICENSE) for more information.\n\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fphpexpertsinc%2Fsimpledto","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fphpexpertsinc%2Fsimpledto","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fphpexpertsinc%2Fsimpledto/lists"}