[英]How can I order NULL values first on a Doctrine 2 collection using annotations?
我有一個使用Symfony 2並包含Doctrine 2實體的項目。 其中一些實體彼此相關。 此關聯由注釋定義:
/**
* @ORM\OneToMany(targetEntity="Event", mappedBy="firstEntityId" cascade={"persist", "remove"})
* @ORM\OrderBy({"dateEnd" = "DESC", "dateBegin" = "DESC"})
*/
private $events;
如您所見,此關聯包含多個具有開始日期和結束日期的事件。 在檢索此集合時,我希望最多的事件(即那些尚未結束或最近結束的事件)先排序。
當前方法的問題在於它將在所有其他事件之后對結束日期為NULL
事件進行排序。
如何告訴Doctrine首先對結束日期為NULL
的事件進行排序,然后按降序結束日期對剩余事件進行排序?
到目前為止,我已經看到了幾個關於如何告訴Doctrine如何訂購實體的問題。 但是,他們都沒有提到注釋。 例如在Doctrine 2 Order By ASC中建議的反轉符號的技巧和最后的Null值不起作用,因為Doctrine在注釋中不接受除屬性名稱和ASC
或DESC
之外的任何內容。
這是一篇舊帖子,但如果你使用的是doctrine查詢構建器,我發現了一個非常簡單的解決方案:
$sortDirection = 'ASC';
$qb = $this->createQueryBuilder('e');
$qb->addSelect('CASE WHEN e.valueToOrder IS NULL THEN 1 ELSE 0 END AS HIDDEN myValueIsNull');
//other stuffs
//$qb->where ...
$qb->orderBy('myValueIsNull','ASC');
$qb->addOrderBy('e.valueToOrder',':sortDirection');
$qb->setParameter(':sortDirection',$sortDirection);
return $qb->getQuery()->getResult();
PHP的方式,除了慢一點,避免使用偏移(例如無限滾動)
可能不是。 有一種SQL語法允許ORDER BY column DESC NULLS FIRST
。 但是,並非所有數據庫供應商都支持它,因此如果我正確掃描了合並請求,則尚未合並到DQL中 。 根據您使用的數據庫平台,您可能會很幸運。 合並請求中的注釋提供了如何在不同點擴展Doctrine以實現行為的洞察力,這可能有助於您自己完成。
我有同樣的問題,這是我的方法:
如果我們不是在談論大量的處理,你可以使用自定義排序,我需要根據用戶選擇將結果按asc或desc中的列排序。 但是,我還需要首先出現相同列的空值。 因此,經過大量谷歌搜索NULLS FIRST方法后,我決定在從查詢構建器獲得結果后立即進行操作:
// Custom sort to put the nulls first
usort($invoices, function(Entity $a, Entity $b) use ($order) {
if(null === $a->getNumber())
return -1;
if(null === $b->getNumber())
return 1;
if(strtoupper($order) == "DESC") {
if($a->getNumber() > $b->getNumber())
return -1;
if($b->getNumber() > $a->getNumber())
return 1;
} else {
if($a->getNumber() < $b->getNumber())
return -1;
if($b->getNumber() < $a->getNumber())
return 1;
}
});
這樣,當您從QueryBuilder獲得結果時,您將首先獲得NULLS,然后您將獲得原始排序。 如果它是ASC,它將保持ASC,反之亦然。
如果最后需要NULL值,您只需要將第一個'if'更改為相反的符號。
我知道這個問題已經回答了,但我想我可以把它放在這里以防它幫助其他人。
我的解決方法是創建為查詢添加一個額外的選擇並從結果數組集合中提取實體,最好只在查詢時檢查它而不選擇它(保持結果數組完整)但我還沒有找到了一個合適的解決方案(使用QueryBuilder
)。
$queryBuilder = $this->getEntityManager()->createQueryBuilder();
$queryBuilder->select('e')
->from(Entity::class, 'e')
// We use ZZZZ here as placeholder to push the null values last, use 'AAAA' to sort them first.
->addSelect('CASE WHEN(e.name IS NULL) THEN \'ZZZZ\' ELSE e.name END AS name')
->addOrderBy('name', 'ASC');
// As we have a array result due to the "addSelect()" above, we must extract the entities now, in this example by looping over the result array.
$entities = array_map(function ($contributor) {
return $contributor[0];
}, $queryBuilder->getQuery()->getResult());
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.