{"id":13608071,"url":"https://github.com/yzen-dev/plain-to-class","last_synced_at":"2025-12-30T00:18:21.928Z","repository":{"id":38081195,"uuid":"348728507","full_name":"yzen-dev/plain-to-class","owner":"yzen-dev","description":"Class-transformer to transform your data into a typed object","archived":false,"fork":false,"pushed_at":"2023-11-15T15:35:21.000Z","size":307,"stargazers_count":166,"open_issues_count":0,"forks_count":8,"subscribers_count":3,"default_branch":"master","last_synced_at":"2024-04-25T10:21:41.661Z","etag":null,"topics":["class-transformer","convert","dataset","php"],"latest_commit_sha":null,"homepage":"https://plain-to-class.readthedocs.io/en/latest/","language":"PHP","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":null,"status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/yzen-dev.png","metadata":{"files":{"readme":"README.RU.md","changelog":null,"contributing":null,"funding":null,"license":null,"code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null}},"created_at":"2021-03-17T13:54:41.000Z","updated_at":"2024-02-26T16:07:49.000Z","dependencies_parsed_at":"2023-02-17T22:31:22.881Z","dependency_job_id":"2c3d54e8-d12a-4f23-ac56-7a6425e1aebb","html_url":"https://github.com/yzen-dev/plain-to-class","commit_stats":{"total_commits":109,"total_committers":3,"mean_commits":"36.333333333333336","dds":"0.47706422018348627","last_synced_commit":"7d175229d590e6556b2966ce04b8222b1ad64fc1"},"previous_names":[],"tags_count":22,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/yzen-dev%2Fplain-to-class","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/yzen-dev%2Fplain-to-class/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/yzen-dev%2Fplain-to-class/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/yzen-dev%2Fplain-to-class/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/yzen-dev","download_url":"https://codeload.github.com/yzen-dev/plain-to-class/tar.gz/refs/heads/master","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":248581247,"owners_count":21128132,"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":["class-transformer","convert","dataset","php"],"created_at":"2024-08-01T19:01:24.009Z","updated_at":"2025-12-30T00:18:21.898Z","avatar_url":"https://github.com/yzen-dev.png","language":"PHP","funding_links":[],"categories":["PHP"],"sub_categories":[],"readme":"## ClassTransformer\n\n![Packagist Version](https://img.shields.io/packagist/v/yzen.dev/plain-to-class?color=blue\u0026label=version)\n![GitHub Workflow Status](https://img.shields.io/github/workflow/status/yzen-dev/plain-to-class/Run%20tests?label=tests\u0026logo=github)\n[![Coverage](https://codecov.io/gh/yzen-dev/plain-to-class/branch/master/graph/badge.svg?token=QAO8STLPMI)](https://codecov.io/gh/yzen-dev/plain-to-class)\n![License](https://img.shields.io/github/license/yzen-dev/plain-to-class)\n![Packagist Downloads](https://img.shields.io/packagist/dm/yzen.dev/plain-to-class)\n![Packagist Downloads](https://img.shields.io/packagist/dt/yzen.dev/plain-to-class)\n\n\nЭта библиотека позволит вам легко преобразовать любой набор данных в нужный вам объект. От вас не требуется менять структуру классов, наследовать их от внешних модулей и т.д. Никаких танцев с бубнами - только данные и нужный класс.\n\nХорошей практикой считается написание кода независимого от сторонних пакетов и фреймворков. Код разбивается на сервисы, доменные зоны, различные слои и т.д. Для передачи данных между слоями, как правило, используется шаблон DataTransfer Object (DTO). DTO - это объект, который необходим для инкапсуляции данных и отправки их из одной подсистемы приложения в другую.\n\nТаким образом, сервисы/методы работают с конкретным объектом и данными необходимым для него. При этом неважно, откуда эти данные были получены - это может быть http запрос, БД, файл и т.д.\n\nСоответственно, при каждом вызове сервиса нам необходимо инициализировать данное DTO. Но сопоставлять каждый раз данные вручную - неэффективно, и сказывается на читабельности кода, особенно если объект сложный.\n\nЗдесь на помощь приходит данный пакет, который берет на себя всю работу с мапингом и инициализацией необходимой DTO.\n\n## :scroll: **Установка**\n\nПакет может быть установлен с помощью composer:\n\n```\nкомпозитору требуется yzen.dev/plain-to-class\n```\n\n\u003e Примечание: Текущая версия пакета поддерживает только PHP 8.1 +.\n\n\u003e Для PHP версии 7.4 вы можете ознакомиться с документацией\n\u003e в [версия v0.*](https://github.com/yzen-dev/plain-to-class/tree/php-7.4 ).\n\u003e\n\u003eДля PHP версии 8.0 вы можете ознакомиться с документацией\n\u003e в [версия v1.*](https://github.com/yzen-dev/plain-to-class/tree/php-8.0 ).\n\n## :scroll: **Использование**\n\nОбщий вариант использования:\n\n### :scroll: **Base**\n\n```\nnamespace DTO;\n\nclass CreateUserDTO\n{\n    public string $email;\n    public float $balance;\n}\n```\n\n```php \n$data = [\n    'email' =\u003e 'test@mail.com',\n    'balance' =\u003e 128.41,\n];\n$dto = ClassTransformer::transform(CreateUserDTO::class, $data);\nvar_dump($dto);\n```\n\nResult:\n\n```php\nobject(\\LoginDTO)\n  'email' =\u003e string(13) \"test@mail.com\"\n  'balance' =\u003e float(128.41) \n```\n\nТакже с версии php 8 вы можете передавать именованные аргументы:\n\n```php \n$dto = ClassTransformer::transform(CreateUserDTO::class,\n        email: 'test@mail.com',\n        balance: 128.41\n      );\n```\n\nЕсли свойство не является скалярным типом, и у него явно указан класс, оно будет автоматически рекурсивно к нему\nприведено.\n\n```php\nclass ProductDTO\n{\n    public int $id;\n    public string $name;\n}\n\nclass PurchaseDTO\n{\n    public ProductDTO $product;\n    public float $cost;\n}\n\n$data = [\n    'product' =\u003e ['id' =\u003e 1, 'name' =\u003e 'phone'],\n    'cost' =\u003e 10012.23,\n];\n\n$purchaseDTO = ClassTransformer::transform(PurchaseDTO::class, $data);\nvar_dump($purchaseDTO);\n```\n\nРезультат:\n\n```php\nobject(PurchaseDTO)\n  public ProductDTO 'product' =\u003e \n    object(ProductDTO)\n      public int 'id' =\u003e int 1\n      public string 'name' =\u003e string 'phone' (length=5)\n  public float 'cost' =\u003e float 10012.23\n```\n\n### :scroll: **Коллекция**\n\nЕсли у вас есть массив объектов определенного класса, то вы должны указать для него атрибут ConvertArray, передав ему в какой класс вам нужно привести элементы.\n\nТакже можно указать класс в PHP DOC, но тогда вам нужно написать полный путь к этому классу `array \u003c\\DTO\\ProductDTO\u003e`.\nЭто делается для того, чтобы точно знать, какой экземпляр нужно создать. Поскольку Reflection не предоставляет готовых\nфункций для получения файла `use`. Помимо `use`, вы можете указать псевдоним и его будет сложнее отследить. Пример:\n\n```php\n\nclass ProductDTO\n{\n    public int $id;\n    public string $name;\n}\n\nclass PurchaseDTO\n{\n    #[ConvertArray(ProductDTO::class)]\n    public array $products;\n}\n\n$data = [\n    'products' =\u003e [\n        ['id' =\u003e 1, 'name' =\u003e 'phone',],\n        ['id' =\u003e 2, 'name' =\u003e 'bread',],\n    ],\n];\n$purchaseDTO = ClassTransformer::transform(PurchaseDTO::class, $data);\n```\n\n#### :scroll: **Анонимная коллекция**\n\nВ случае если вам нужно преобразовать массив данных в массив объектов класса, вы можете реализовать это с помощью\nметода `transformCollection`.\n\n```php\n$data = [\n  ['id' =\u003e 1, 'name' =\u003e 'phone'],\n  ['id' =\u003e 2, 'name' =\u003e 'bread'],\n];\n$products = ClassTransformer::transformCollection(ProductDTO::class, $data);\n```\n\nВ результате этого вы получите массив объектов ProductDTO\n\n```php\narray(2) {\n  [0]=\u003e\n      object(ProductDTO) {\n        [\"id\"]=\u003e int(1)\n        [\"name\"]=\u003e string(5) \"phone\"\n      }\n  [1]=\u003e\n      object(ProductDTO) {\n        [\"id\"]=\u003e int(2)\n        [\"name\"]=\u003e string(5) \"bread\"\n      }\n} \n```\n\nВам также может потребоваться поэлементное преобразование массива. В таком случае вы можете передать массив классов,\nкоторый затем можно легко распаковать\n\n```php\n    $userData = ['id' =\u003e 1, 'email' =\u003e 'test@test.com', 'balance' =\u003e 10012.23];\n    $purchaseData = [\n        'products' =\u003e [\n            ['id' =\u003e 1, 'name' =\u003e 'phone',],\n            ['id' =\u003e 2, 'name' =\u003e 'bread',],\n        ],\n        'user' =\u003e ['id' =\u003e 3, 'email' =\u003e 'fake@mail.com', 'balance' =\u003e 10012.23,],\n    ];\n\n    $result = ClassTransformer::transformMultiple([UserDTO::class, PurchaseDTO::class], [$userData, $purchaseData]);\n    \n    [$user, $purchase] = $result;\n    var_dump($user);\n    var_dump($purchase);\n```\n\nResult:\n\n```php\nobject(UserDTO) (3) {\n  [\"id\"] =\u003e int(1)\n  [\"email\"]=\u003e string(13) \"test@test.com\"\n  [\"balance\"]=\u003e float(10012.23)\n}\n\nobject(PurchaseDTO) (2) {\n  [\"products\"]=\u003e\n  array(2) {\n    [0]=\u003e\n    object(ProductDTO)#349 (3) {\n      [\"id\"]=\u003e int(1)\n      [\"name\"]=\u003e string(5) \"phone\"\n    }\n    [1]=\u003e\n    object(ProductDTO)#348 (3) {\n      [\"id\"]=\u003e int(2)\n      [\"name\"]=\u003e string(5) \"bread\"\n    }\n  }\n  [\"user\"]=\u003e\n  object(UserDTO)#332 (3) {\n    [\"id\"]=\u003e int(3)\n    [\"email\"]=\u003e string(13) \"fake@mail.com\"\n    [\"balance\"]=\u003e float(10012.23)\n  }\n}\n```\n\n### :scroll: ** Стиль написания**\n\nПостоянная проблема со стилем написания, например, в базе данных это snake_case, а в коде camelCase.\nИ их постоянно нужно как-то трансформировать. Пакет позаботится об этом, вам просто нужно указать\nатрибут WritingStyle в свойстве:\n\n```php\nclass WritingStyleSnakeCaseDTO\n{\n    #[WritingStyle(WritingStyle::STYLE_CAMEL_CASE, WritingStyle::STYLE_SNAKE_CASE)]\n    public string $contact_fio;\n\n    #[WritingStyle(WritingStyle::STYLE_CAMEL_CASE)]\n    public string $contact_email;\n}\n\n\n $data = [\n  'contactFio' =\u003e 'yzen.dev',\n  'contactEmail' =\u003e 'test@mail.com',\n];\n$model = ClassTransformer::transform(WritingStyleSnakeCaseDTO::class, $data);\nvar_dump($model);\n```\n\n```php\nRESULT:\n\nobject(WritingStyleSnakeCaseDTO) (2) {\n  [\"contact_fio\"]=\u003e string(8) \"yzen.dev\"\n  [\"contact_email\"]=\u003e string(13) \"test@mail.com\"\n}\n```\n\n### :scroll: **Alias**\n\nДля свойства можно задать различные возможные alias'ы, которые будут также искаться в источнике данных. Это может быть\nполезно если DTO формируется по разным источникам данных.\n\n```php\nclass WithAliasDTO\n{\n    #[FieldAlias('userFio')]\n    public string $fio;\n\n    #[FieldAlias(['email', 'phone'])]\n    public string $contact;\n}\n```\n\n### :scroll: **Кастомизация сеттеров**\n\nЕсли поле требует дополнительной обработки при его инициализации, вы можете мутировать его сеттер. Для это создайте в\nклассе метод следующего формата -  `set{$name}Attribute`. Пример:\n\n```php\nclass UserDTO\n{\n    public int $id;\n    public string $real_address;\n\n    public function setRealAddressAttribute(string $value)\n    {\n        $this-\u003ereal_address = strtolower($value);\n    }\n}\n```\n\n### :scroll: **Пост обработка**\n\nВнутри класса вы можете создать метод `afterTransform`, который вызовется сразу по завершению преобразования. В нем мы\nможете описать свою дополнительную логику проверки или преобразования работая уже с состоянием объекта.\n\n```php\nclass UserDTO\n{\n    public int $id;\n    public float $balance;\n\n    public function afterTransform()\n    {\n        $this-\u003ebalance = 777;\n    }\n}\n```\n\n### :scroll: **Кастомное преобразование**\n\nЕсли вам требуется полностью свое преобразование, то вы можете в классе создать метод transform. В таком случае никакие\nобработки библиотеки не вызываются, вся ответственность преобразования переходит на ваш класс.\n\n```php\nclass CustomTransformUserDTOArray\n{\n    public string $email;\n    public string $username;\n    \n    public function transform($args)\n    {\n        $this-\u003eemail = $args['login'];\n        $this-\u003eusername = $args['fio'];\n    }\n}\n```\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fyzen-dev%2Fplain-to-class","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fyzen-dev%2Fplain-to-class","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fyzen-dev%2Fplain-to-class/lists"}