php-ddd
php-ddd copied to clipboard
PHP Arrays vs. DTO READ models / VIEW collections using Doctrine
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