Поскольку $row->getCountryWeights()
вернет объект Collection
, вам необходимо проверить коллекцию.
$countryWeights = $row->getCountryWeights(); //Collection object
$rowOut['weight'] = (($firstWeight = $countryWeights->first()) ? $firstWeight->getWeight() : 0);
Использование Collection::first()
вернет false
или первую запись в коллекции, вызвав reset()
во внутреннем массиве коллекции.
В противном случае вы можете проверить, является ли Коллекция пустой, используя $row->getCountryWeights()->isEmpty()
.
Explaination
Пример 1:
Скажем, у вас есть следующий набор данных;
\ CampaignBundle \ Entity \ Kpi
| id |
| 1 |
| 2 |
\ CampaignBundle \ Entity \ Kpi :: $ countryWeights (OneToMany(targetEntity="CampaignBundle\Entity\CountryWeight"))
| kpi_id | country | weight |
| 1 | A | 1 |
| 1 | B | 1 |
| 2 | A | 1 |
По умолчанию доктрина Lazy Load
ассоциирует сущности CountryWeight при вызове метода получения.
$allRows = $em->getRepository(\CampaignBundle\Entity\Kpi::class)->findAll();
$data = [];
foreach ($allRows as $row) {
foreach ($row->getCountryWeights() as $weight) {
$data[$row->getId()][$weight->getCountry()] = $weight->getWeight();
}
}
dump($data);
Результатом является Ленивая загрузка ассоциаций CountryWeight:
array:2 [▼
1 => array:2 [▼
"A" => 1
"B" => 1
]
2 => array:1 [▼
"A" => 1
]
]
Пример 2:
Однако при использовании QueryBuilder
Коллекция ограничивается в соответствии с указанными критериями Join:WITH
.
$allRows = $em->getRepository(\CampaignBundle\Entity\Kpi::class)->createQueryBuilder('k')
->leftJoin('k.countryWeights', 'w', Join::WITH, $expr->eq('w.country', ':country'))
->setParameter('country', 'B')//<--- NOTE B is filtered
->addSelect('w')
->getQuery()
->getResult();
$data = [];
foreach ($allRows as $row) {
$firstWeight = $row->getCountryWeights()->first();
$data[$row->getId()][$firstWeight ? $firstWeight->getCountry() : null] = $firstWeight ? $firstWeight->getWeight() : 0;
}
dump($data);
Результатом будет:
array:2 [▼
1 => array:1 [▼
"B" => 1
]
2 => array:1 [▼
"" => 0
]
]
В том случае, если доктрина уже извлекла ассоциации CountryWeight
, такие как выполнение примера 1, за которым следует пример 2. Вам нужно будет указать доктрине, чтобы принудительно очистить UnitOfWork
[sic] для получить отфильтрованные записи из базы данных, в противном случае он будет использовать уже загруженные коллекции для полученных результатов.
Одним из способов достижения этого является выдача
$em->clear(\CampaignBundle\Entity\Kpi::class);
До выполнения вашего запроса. Который очистит всю единицу работы доктрины для объекта. При использовании Query::HINT_REFRESH
не будет полностью обновляться исключенные значения из Kpi :: $ id => 2 со страной A.
Пример вывода из уже найденных ассоциаций.
![Doctrine Dump](https://i.stack.imgur.com/UVqcO.png)
Рекомендации:
Doctrine позволяет вам обходить все ассоциации между всеми объектами в вашей доменной модели. Объекты, которые еще не были загружены из базы данных, заменяются экземплярами прокси с отложенной загрузкой. Незагруженные коллекции также заменяются экземплярами с отложенной загрузкой, которые извлекают все содержащиеся в них объекты при первом доступе. Однако использование механизма отложенной загрузки приводит к выполнению множества небольших запросов к базе данных, что может существенно повлиять на производительность вашего приложения. Выборочные соединения - это решение для гидратации большинства или всех сущностей, которые вам нужны, в одном запросе SELECT.
https://www.doctrine -project.org / проекты / Доктрина-ОРМ / ен / 2,6 / ссылки / DQL-доктрина-запрос-language.html # присоединяется
Если объект уже находится в памяти из предыдущего запроса любого типа, тогда используется предыдущий объект, даже если база данных может содержать более свежие данные. Данные из базы данных отбрасываются. Это даже происходит, если предыдущий объект все еще является незагруженным прокси.
https://www.doctrine -project.org / проекты / Доктрина-ОРМ / ы / 2,6 / ссылки / DQL-доктрина-запросы language.html # объекта-гидратация