I have huge query with many leftJoins. All the leftJoin, except of one, is associated in the entities. The one, which does not gets every time an own entry, if I use the array hydration mode.
Basically, I am using Shopware and this query is part of a plugin. However, every referenced Entity, except of my own, can be found at the Shopware GitHub repo: https://github.com/shopware/shopware/blob/5.3/engine/Shopware/Models/Order/Order.php
My query in my repository:
$builder = $this->getEntityManager()->createQueryBuilder();
$builder->select([
'orders',
'details',
'payment.id',
'payment.name',
'payment.description',
'payment.action',
'payment.pluginId',
'paymentInstances',
'shipping',
'billing',
'billingCountry',
'shippingCountry',
'paymentPayPal',
'paymentStatus',
]);
$builder->from('Shopware\Models\Order\Order', 'orders');
$builder->leftJoin('orders.details', 'details')
->leftJoin('orders.payment', 'payment')
->leftJoin('orders.paymentInstances', 'paymentInstances')
->leftJoin('SapExport\Models\PaymentPayPal', 'paymentPayPal', \Doctrine\ORM\Query\Expr\Join::WITH, 'orders.number = paymentPayPal.ordernumber AND payment.name = \'paypal\'')
->leftJoin('orders.billing', 'billing')
->leftJoin('billing.country', 'billingCountry')
->leftJoin('orders.shipping', 'shipping')
->leftJoin('shipping.country', 'shippingCountry')
->leftJoin('orders.paymentStatus', 'paymentStatus');
$builder->where('orders.cleared = ' . Status::PAYMENT_STATE_COMPLETELY_PAID)
->andWhere($builder->expr()->notIn('orders.id', $this->getSapExportIdsQuery()->getDQL()));
$builder->orderBy('orders.id', 'DESC');
The subselect query in where
clause:
$builder = $this->getEntityManager()->createQueryBuilder();
$builder->select([
'sapExport.id'
]);
$builder->from('SapExport\Models\SapExport', 'sapExport');
If I hydrate it to array it outputs something like this (json encoded data):
[
[
{
"id": 10353,
"number": "650004023",
"customerId": 4235,
"status": 0,
"cleared": 12,
"paymentId": 7,
"dispatchId": 10,
"partnerId": "",
"shopId": 1,
"invoiceAmount": 99.95,
"invoiceAmountNet": 83.99,
"invoiceShipping": 0,
"invoiceShippingNet": 0,
...
"details": [
{
...
}
],
"paymentInstances": [
{
...
}
],
"billing": {
...
},
"shipping": {
...
},
"paymentStatus": {
...
}
}
],
{
"0": {
"id": 251,
"ordernumber": "650004023",
"referenceNumber": "34TEST",
"instructionType": "TEST",
"bankName": "bank name",
"accountHolder": "PayPal Europe",
"iban": "DEXXXXXX",
"amountValue": "99.95",
"amountCurrency": "EUR",
"paymentDueDate": {
"date": "2018-01-31 00:00:00.000000",
"timezone_type": 3,
"timezone": "Europe\/Berlin"
},
"links": "[{\"href\":\"https://www.example.com\",\"rel\":\"self\",\"method\":\"GET\"}]"
},
"id": 7,
"name": "paypal",
"description": "PayPal",
"action": "payment_paypal",
"pluginId": 64
}
]
Needed result / Expected result:
[
[
{
"id": 10353,
"number": "650004023",
"customerId": 4235,
"status": 0,
"cleared": 12,
"paymentId": 7,
"dispatchId": 10,
"partnerId": "",
"shopId": 1,
"invoiceAmount": 99.95,
"invoiceAmountNet": 83.99,
"invoiceShipping": 0,
"invoiceShippingNet": 0,
...
"details": [
{
...
}
],
"paymentInstances": [
{
...
}
],
"billing": {
...
},
"shipping": {
...
},
"paymentStatus": {
...
},
"paymentPayPal": {
"id": 251,
"ordernumber": "650004023",
"referenceNumber": "34TEST",
"instructionType": "TEST",
"bankName": "bank name",
"accountHolder": "PayPal Europe",
"iban": "DEXXXXXX",
"amountValue": "99.95",
"amountCurrency": "EUR",
"paymentDueDate": {
"date": "2018-01-31 00:00:00.000000",
"timezone_type": 3,
"timezone": "Europe\/Berlin"
},
"links": "[{\"href\":\"https://www.example.com\",\"rel\":\"self\",\"method\":\"GET\"}]"
},
"payment": {
"id": 7,
"name": "paypal",
"description": "PayPal",
"action": "payment_paypal",
"pluginId": 64
}
}
]
]
If I execucte the SQL on the database, the result set is as expected. So, it seems to be a strange doctrine entity mapping.
Edit: For clearance to my actually problem, that I have: The entity payment
is not on the main entity, called orders
. It gets an own object, right next to orders
in the array result set. So, we have two issues there:
payment
is an object, not an array.- It gets an own entry, but it should appear under the
orders
entry in result set.
Also, paymentPayPal
entity does completely not appear in the result set. But it should, because I selected it as well.
Edit 2: This is the resulting DQL Query (please note that I reduced details
entity a bit, since I don't need all columns of it):
SELECT orders, details.id, details.articleId, details.number, details.articleNumber, details.price, details.quantity, details.articleName, details.mode, details.esdArticle, details.unit, details.packUnit, payment.id, payment.name, payment.description, payment.action, payment.pluginId, paymentInstances, shipping, billing, billingCountry, shippingCountry, paymentPayPal, paymentStatus FROM Shopware\Models\Order\Order orders LEFT JOIN orders.details details LEFT JOIN orders.payment payment LEFT JOIN orders.paymentInstances paymentInstances LEFT JOIN SapExport\Models\PaymentPayPal paymentPayPal WITH orders.number = paymentPayPal.ordernumber AND payment.name = 'paypal' LEFT JOIN orders.billing billing LEFT JOIN billing.country billingCountry LEFT JOIN orders.shipping shipping LEFT JOIN shipping.country shippingCountry LEFT JOIN orders.paymentStatus paymentStatus WHERE orders.cleared = 12 AND orders.id NOT IN(SELECT sapExport.id FROM SapExport\Models\SapExport sapExport) ORDER BY orders.id DESC
Edit 3: The query works fine, if I do not leftJoin the paypal table. I need this table to get additional informations, if the customer has choosen paypal as the payment type for his oder her order. But only for this type I need those additional informations. As far as I know, leftJoin should do the trick. Because, if it's not paypal, it should join an empty record set with null
ed columns. But I am wondering why Doctrine behaves this way, the SQL Query pendant works well...