diff --git a/README.md b/README.md index ce4fea1..cbdaf11 100644 --- a/README.md +++ b/README.md @@ -5,47 +5,21 @@ This bundle aims to solve the problem of building nested DTOs from flat arrays (such as database queries results). -## Introduction +One of its purposes is to help you create DTOs the same way you would with the Doctrine `NEW` keyword, except at depth. Other ways to do that generally imply mapping entities to DTOs which is less performant (memory and CPU wise). You can find benchmarks for this package at [Pixelshaped/flat-mapper-benchmark](https://github.com/Pixelshaped/flat-mapper-benchmark). -Doctrine [provides a solution](https://www.doctrine-project.org/projects/doctrine-orm/en/2.11/reference/dql-doctrine-query-language.html#new-operator-syntax) to build DTOs directly from a QueryBuilder: - -Given a DTO class such as `CustomerDTO`: - -```php -`: - -```php -createQuery('SELECT NEW CustomerDTO(c.name, e.email, a.city) FROM Customer c JOIN c.email e JOIN c.address a'); -$users = $query->getResult(); // array -``` +## How to use? -Unfortunately, if you need to retrieve DTOs with non-scalar properties, such as: +### At a glance -- an array of IDs -- an array of nested DTOs - -then, the solution provided by Doctrine doesn't work. The creation of this bundle arose from that situation. With it, you can do: +Given a DTO such as [AuthorDTO](tests/Examples/Valid/ReferencesArray/AuthorDTO.php) -```php -$flatMapper->map(NonScalarCustomerDTO::class, $query->getArrayResult()); +```php +$result = $flatMapper->map(AuthorDTO::class, $authorRepository->getAuthorsAndTheirBooks()); ``` -### Naming - -While using Object-Relational Mapping techniques, this package is not a full-fledged ORM in the accepted sense of the word, as it only handles the mapping of "flat" data to objects. Hence, the name "Flat Mapper". - -### Purpose - -Its purpose is to help you create DTOs the same way you would with the Doctrine `NEW` keyword, except at depth. Other ways to do that generally imply mapping entities to DTOs which is less performant (memory and CPU wise). You can find benchmarks for this package at [Pixelshaped/flat-mapper-benchmark](https://github.com/Pixelshaped/flat-mapper-benchmark). -## How to use? +Will give you an array of `AuthorDTO` hydrated with all their `BookDTO` books (See [complete example](#complete_example)). ### Installation @@ -107,6 +81,7 @@ This bundle comes with several attributes that you can use to add mapping to you - `#[ReferencesArray(NestedDTO::class)]`: An array of `NestedDTO` will be created using the mapping information contained in `NestedDTO`. - `#[ColumnArray("mapped_property_name")]` the column `mapped_property_name` of your result set will be mapped as an array of scalar properties (such as IDs). + ### Hydrating nested DTOs Given: @@ -125,7 +100,7 @@ $results = [ ['author_id' => 2, 'author_name' => 'Bob Schmo', 'book_id' => 4, 'book_name' => 'My best recipes', 'book_publisher_name' => 'Cooking and Stuff'], ]; -$flatMapper->map(RootDTO::class, $results); +$flatMapper->map(AuthorDTO::class, $results); ``` Will output: @@ -290,6 +265,33 @@ You can use this package without Symfony. Just instantiate the `FlatMapper` clas ## Alternatives +Doctrine [provides a solution](https://www.doctrine-project.org/projects/doctrine-orm/en/2.11/reference/dql-doctrine-query-language.html#new-operator-syntax) to build DTOs directly from a QueryBuilder: + +Given a DTO class such as `CustomerDTO`: + +```php +`: + +```php +createQuery('SELECT NEW CustomerDTO(c.name, e.email, a.city) FROM Customer c JOIN c.email e JOIN c.address a'); +$users = $query->getResult(); // array +``` + +Unfortunately, if you need to retrieve DTOs with non-scalar properties, such as: + +- an array of IDs +- an array of nested DTOs + +then, the solution provided by Doctrine doesn't work. The creation of this bundle arose from that situation. + When I started coding this, I looked for alternatives but found only partial ones: - [mark-gerarts/automapper-plus](https://github.com/mark-gerarts/automapper-plus) is great at mapping objects to other objects (namely, entities to DTOs and vice versa), but doesn't solve the problem of mapping denormalized data (i.e. an array with the information for several objects on each row and a lot of redundancy between rows) to objects.