php-ddd icon indicating copy to clipboard operation
php-ddd copied to clipboard

PHP Arrays vs. DTO READ models / VIEW collections using Doctrine

Open webdevilopers opened this issue 9 years ago • 0 comments

Currently I'm using PHP Arrays for single READ models. Actually it was a performance driven decision since I use them for exporting 100s of rows into a generated PDF.

But looks like this myth has been busted or at least is no longer regarded "relevant" since PHP_7_:

  • http://stackoverflow.com/questions/2193049/php-objects-vs-arrays
  • https://gist.github.com/nikic/5015323 @nikic
  • https://gist.github.com/Thinkscape/1136563#gistcomment-1672635 @Thinkscape @vejja
  • http://www.brandonsavage.net/stop-returning-arrays-use-objects-instead/ @brandonsavage

Looking at some DDD repository examples Java and DotNET write results coming from a persistence storage into a collection of objects.

Mostly these objects are then serializable to deliver primitive types like Command DTOs.

Currently I'm using the Doctrine Array hydration to handle a more complex query:

  • http://docs.doctrine-project.org/projects/doctrine-orm/en/latest/reference/dql-doctrine-query-language.html#array-hydration
        $qb->select(array(
                'b.id',
                'b.date',
                'b.shift',
                'b.shippingnumber AS shipping_number',
                'GroupConcat(DISTINCT b.comment) AS comment',
                'SUM(b.customFieldNum1) / CASE WHEN COUNT(bps_ok.id) = 0 THEN 1 ELSE COUNT(bps_ok.id) / COUNT(DISTINCT bps_ok.id) AS custom_field_num_1',
                'SUM(b.customFieldNum2) / CASE WHEN COUNT(bps_ok.id) = 0 THEN 1 ELSE COUNT(bps_ok.id) / COUNT(DISTINCT bps_ok.id) AS custom_field_num_2',
                'SUM(b.customFieldNum3) / CASE WHEN COUNT(bps_ok.id) = 0 THEN 1 ELSE COUNT(bps_ok.id) / COUNT(DISTINCT bps_ok.id) AS custom_field_num_3',
                'SUM(b.customFieldNum4) / CASE WHEN COUNT(bps_ok.id) = 0 THEN 1 ELSE COUNT(bps_ok.id) / COUNT(DISTINCT bps_ok.id) AS custom_field_num_4',
                'SUM(b.customFieldNum5) / CASE WHEN COUNT(bps_ok.id) = 0 THEN 1 ELSE COUNT(bps_ok.id) / COUNT(DISTINCT bps_ok.id) AS custom_field_num_5',
                'b.customFieldStr1 AS custom_field_str_1',
                'b.customFieldStr2 AS custom_field_str_2',
                'b.customFieldStr3 AS custom_field_str_3',
                'b.customFieldStr4 AS custom_field_str_4',
                'b.customFieldStr5 AS custom_field_str_5',
                'p.id AS parttype_id',
                'p.integratorNumber AS part_number',
                'l.name AS location',
                'SUM(bps_ok.quantity) / CASE WHEN COUNT(bps_ok.id) = 0 THEN 1 ELSE COUNT(bps_ok.id) / COUNT(DISTINCT bps_ok.id) AS ok_total',
                'SUM(bps_ok.quantity+bps_nok_processed.quantity+bps_nok_blocked.quantity) / CASE WHEN COUNT(bps_ok.id) = 0 THEN 1 ELSE COUNT(bps_ok.id) / COUNT(DISTINCT bps_ok.id) AS total',
                'SUM(bps_nok_processed.quantity+bps_nok_blocked.quantity) / CASE WHEN COUNT(bps_ok.id) = 0 THEN 1 ELSE COUNT(bps_ok.id) / COUNT(DISTINCT bps_ok.id) AS nok_total',
                'SUM(bps_nok_processed.quantity) / CASE WHEN COUNT(bps_ok.id) = 0 THEN 1 ELSE COUNT(bps_ok.id) / COUNT(DISTINCT bps_ok.id) AS nok_processed',
                'SUM(bps_nok_blocked.quantity) / CASE WHEN COUNT(bps_ok.id) = 0 THEN 1 ELSE COUNT(bps_ok.id) / COUNT(DISTINCT bps_ok.id) AS nok_blocked',
            ))

Since Doctrine 2.4 it is possible to directly write a result into a DTO:

  • http://docs.doctrine-project.org/en/latest/reference/dql-doctrine-query-language.html#new-operator-syntax
<?php
class CustomerDetails
{
    public function __construct($name, $email, $city, $value = null)
    {
        // Bind values to the object properties.
    }
}

<?php
$query = $em->createQuery('SELECT NEW CustomerDetails(c.name, e.email, a.city) FROM Customer c JOIN c.email e JOIN c.address a');
$users = $query->getResult(); // array of CustomerDetails

This works for any PHP class / POPO. While using ResultSetMapping only seems to work with Doctrine Entities:

  • http://stackoverflow.com/questions/26441412/can-i-use-resultsetmapping-addentityresult-with-an-entity-that-doesnt-have-a @JonnyD
  • http://doctrine-orm.readthedocs.io/projects/doctrine-orm/en/latest/reference/native-sql.html

What are your experiences / favorited strategies?

Related:

  • https://github.com/webdevilopers/php-ddd/issues/14

webdevilopers avatar Jun 21 '16 09:06 webdevilopers