Skip to content

Commit

Permalink
chore: Improve README.md (#6)
Browse files Browse the repository at this point in the history
  • Loading branch information
Pixelshaped authored Jul 9, 2024
1 parent af9a4dd commit 5ab51b3
Showing 1 changed file with 37 additions and 35 deletions.
72 changes: 37 additions & 35 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -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
class CustomerDTO
{
public function __construct($name, $email, $city, $value = null){ /* ... */ }
}
```
You can also use it to map SQL queries to objects, it has no dependency on a particular ORM.

Doctrine can execute a query that produces an array `array<CustomerDTO>`:

```php
<?php
$query = $em->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<CustomerDTO>
```
## 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

Expand Down Expand Up @@ -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).

<a name="complete_example"></a>
### Hydrating nested DTOs

Given:
Expand All @@ -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:
Expand Down Expand Up @@ -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
class CustomerDTO
{
public function __construct($name, $email, $city, $value = null){ /* ... */ }
}
```

Doctrine can execute a query that produces an array `array<CustomerDTO>`:

```php
<?php
$query = $em->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<CustomerDTO>
```

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.
Expand Down

0 comments on commit 5ab51b3

Please sign in to comment.