Extbase n:m setOrderings() 排序不正确
Extbase n:m setOrderings() does not sort correct
我有课程,它们有多种开始类型和开始日期。
starttype = 1 // date
starttype = 2 // on_request
starttype = 3 // continuously
所以我按开始类型对课程进行排序,然后按开始日期时间对课程进行排序。现在它产生的订单只使用开始中的第一个条目而不是最早的条目。但是,如果我在数据库上使用查询,则排序符合预期。看起来查询和数据库之间有一些 'magic'。我的问题有解决方案吗?
在我的控制器中,我设置了排序,因为我在许多示例中都找到了它
/**
* Find all courses and sort them by start type and start date
* @throws \TYPO3\CMS\Extbase\Persistence\Exception\InvalidQueryException
*/
public function findAllSorted() {
$query = $this->createQuery();
$query->setOrderings([
'starts.starttype' => QueryInterface::ORDER_ASCENDING,
'starts.startdatetime' => QueryInterface::ORDER_ASCENDING
]);
$query->matching(
$query->logicalOr([
$query->greaterThan('starts.starttype',1),
$query->greaterThan('starts.startdatetime', time())
]));
// Debug query
//$queryParser = $this->objectManager->get(\TYPO3\CMS\Extbase\Persistence\Generic\Storage\Typo3DbQueryParser::class);
//\TYPO3\CMS\Extbase\Utility\DebuggerUtility::var_dump($queryParser->convertQueryToDoctrineQueryBuilder($query)->getSQL());
//\TYPO3\CMS\Extbase\Utility\DebuggerUtility::var_dump($queryParser->convertQueryToDoctrineQueryBuilder($query)->getParameters());
return $query->execute();
}
这会产生以下查询
SELECT `tx_vendorcontinuingeducation_domain_model_course`.*
FROM `tx_vendorcontinuingeducation_domain_model_course` `tx_vendorcontinuingeducation_domain_model_course`
LEFT JOIN `tx_vendorcontinuingeducation_domain_model_start` `tx_vendorcontinuingeducation_domain_model_start` ON `tx_vendorcontinuingeducation_domain_model_course`.`uid` = `tx_vendorcontinuingeducation_domain_model_start`.`parent`
WHERE ((`tx_vendorcontinuingeducation_domain_model_start`.`starttype` > :dcValue1)
OR (`tx_vendorcontinuingeducation_domain_model_start`.`startdatetime` > :dcValue2))
AND (`tx_vendorcontinuingeducation_domain_model_course`.`sys_language_uid` IN (0,
-1))
AND (`tx_vendorcontinuingeducation_domain_model_course`.`t3ver_oid` = 0)
AND ((`tx_vendorcontinuingeducation_domain_model_course`.`deleted` = 0)
AND (`tx_vendorcontinuingeducation_domain_model_course`.`t3ver_state` <= 0)
AND (`tx_vendorcontinuingeducation_domain_model_course`.`t3ver_wsid` = 0)
AND (`tx_vendorcontinuingeducation_domain_model_course`.`t3ver_oid` = 0)
AND (`tx_vendorcontinuingeducation_domain_model_course`.`hidden` = 0)
AND (`tx_vendorcontinuingeducation_domain_model_course`.`starttime` <= 1619622660)
AND ((`tx_vendorcontinuingeducation_domain_model_course`.`endtime` = 0)
OR (`tx_vendorcontinuingeducation_domain_model_course`.`endtime` > 1619622660))
AND (((`tx_vendorcontinuingeducation_domain_model_course`.`fe_group` = '')
OR (`tx_vendorcontinuingeducation_domain_model_course`.`fe_group` IS NULL)
OR (`tx_vendorcontinuingeducation_domain_model_course`.`fe_group` = '0')
OR (FIND_IN_SET('0', `tx_vendorcontinuingeducation_domain_model_course`.`fe_group`))
OR (FIND_IN_SET('-1', `tx_vendorcontinuingeducation_domain_model_course`.`fe_group`)))))
AND (((`tx_vendorcontinuingeducation_domain_model_start`.`deleted` = 0)
AND (`tx_vendorcontinuingeducation_domain_model_start`.`t3ver_state` <= 0)
AND (`tx_vendorcontinuingeducation_domain_model_start`.`t3ver_wsid` = 0)
AND (`tx_vendorcontinuingeducation_domain_model_start`.`t3ver_oid` = 0)
AND (`tx_vendorcontinuingeducation_domain_model_start`.`hidden` = 0)
AND (`tx_vendorcontinuingeducation_domain_model_start`.`starttime` <= 1619622660)
AND ((`tx_vendorcontinuingeducation_domain_model_start`.`endtime` = 0)
OR (`tx_vendorcontinuingeducation_domain_model_start`.`endtime` > 1619622660))
AND (((`tx_vendorcontinuingeducation_domain_model_start`.`fe_group` = '')
OR (`tx_vendorcontinuingeducation_domain_model_start`.`fe_group` IS NULL)
OR (`tx_vendorcontinuingeducation_domain_model_start`.`fe_group` = '0')
OR (FIND_IN_SET('0', `tx_vendorcontinuingeducation_domain_model_start`.`fe_group`))
OR (FIND_IN_SET('-1', `tx_vendorcontinuingeducation_domain_model_start`.`fe_group`)))))
OR (`tx_vendorcontinuingeducation_domain_model_start`.`uid` IS NULL))
ORDER BY `tx_vendorcontinuingeducation_domain_model_start`.`starttype` ASC,
`tx_vendorcontinuingeducation_domain_model_start`.`startdatetime` ASC
和值
array(2 items)
dcValue1 => 1 (integer)
dcValue2 => 1619622708 (integer)
现在我替换 dcValues 并将它们复制到我的 phpMyAdmin
SELECT `tx_vendorcontinuingeducation_domain_model_course`.*
FROM `tx_vendorcontinuingeducation_domain_model_course` `tx_vendorcontinuingeducation_domain_model_course`
LEFT JOIN `tx_vendorcontinuingeducation_domain_model_start` `tx_vendorcontinuingeducation_domain_model_start` ON `tx_vendorcontinuingeducation_domain_model_course`.`uid` = `tx_vendorcontinuingeducation_domain_model_start`.`parent`
WHERE ((`tx_vendorcontinuingeducation_domain_model_start`.`starttype` > 1)
OR (`tx_vendorcontinuingeducation_domain_model_start`.`startdatetime` > 1619619086))
AND (`tx_vendorcontinuingeducation_domain_model_course`.`sys_language_uid` IN (0,
-1))
AND (`tx_vendorcontinuingeducation_domain_model_course`.`t3ver_oid` = 0)
AND ((`tx_vendorcontinuingeducation_domain_model_course`.`deleted` = 0)
AND (`tx_vendorcontinuingeducation_domain_model_course`.`t3ver_state` <= 0)
AND (`tx_vendorcontinuingeducation_domain_model_course`.`t3ver_wsid` = 0)
AND (`tx_vendorcontinuingeducation_domain_model_course`.`t3ver_oid` = 0)
AND (`tx_vendorcontinuingeducation_domain_model_course`.`hidden` = 0)
AND (`tx_vendorcontinuingeducation_domain_model_course`.`starttime` <= 1619619060)
AND ((`tx_vendorcontinuingeducation_domain_model_course`.`endtime` = 0)
OR (`tx_vendorcontinuingeducation_domain_model_course`.`endtime` > 1619619060))
AND (((`tx_vendorcontinuingeducation_domain_model_course`.`fe_group` = '')
OR (`tx_vendorcontinuingeducation_domain_model_course`.`fe_group` IS NULL)
OR (`tx_vendorcontinuingeducation_domain_model_course`.`fe_group` = '0')
OR (FIND_IN_SET('0', `tx_vendorcontinuingeducation_domain_model_course`.`fe_group`))
OR (FIND_IN_SET('-1', `tx_vendorcontinuingeducation_domain_model_course`.`fe_group`)))))
AND (((`tx_vendorcontinuingeducation_domain_model_start`.`deleted` = 0)
AND (`tx_vendorcontinuingeducation_domain_model_start`.`t3ver_state` <= 0)
AND (`tx_vendorcontinuingeducation_domain_model_start`.`t3ver_wsid` = 0)
AND (`tx_vendorcontinuingeducation_domain_model_start`.`t3ver_oid` = 0)
AND (`tx_vendorcontinuingeducation_domain_model_start`.`hidden` = 0)
AND (`tx_vendorcontinuingeducation_domain_model_start`.`starttime` <= 1619619060)
AND ((`tx_vendorcontinuingeducation_domain_model_start`.`endtime` = 0)
OR (`tx_vendorcontinuingeducation_domain_model_start`.`endtime` > 1619619060))
AND (((`tx_vendorcontinuingeducation_domain_model_start`.`fe_group` = '')
OR (`tx_vendorcontinuingeducation_domain_model_start`.`fe_group` IS NULL)
OR (`tx_vendorcontinuingeducation_domain_model_start`.`fe_group` = '0')
OR (FIND_IN_SET('0', `tx_vendorcontinuingeducation_domain_model_start`.`fe_group`))
OR (FIND_IN_SET('-1', `tx_vendorcontinuingeducation_domain_model_start`.`fe_group`)))))
OR (`tx_vendorcontinuingeducation_domain_model_start`.`uid` IS NULL))
ORDER BY `tx_vendorcontinuingeducation_domain_model_start`.`starttype` ASC,
`tx_vendorcontinuingeducation_domain_model_start`.`startdatetime` ASC
phpMyAdmin 中的排序是正确的。这是一个错误还是我该如何解决?
Slack 上的对话表明无法使用 Extbase 按 n:m 值排序。这只有在 1:1 依赖项下才有可能。
我们随后解决了它。在获得通缉课程后,我们将它们排序为数组。如果您想对其进行分页,则可以使用新的 PaginatorAPI 中的 ArrayPaginator。
$coursesArray = $courses->toArray();
$sortedCourseArray = Array();
$sortedCourseType1 = Array();
$sortedCourseType2 = Array();
$sortedCourseType3 = Array();
foreach ($coursesArray as $course) {
$starts =$course->getStarts()->toArray();
usort($starts, function ($a, $b) {
return $a->getStarttype() > $b->getStarttype();
});
foreach ($starts as $start){
if($start->getStarttype() == 1){
array_push($sortedCourseType1, $course);
break;
}
if($start->getStarttype() == 2){
array_push($sortedCourseType2, $course);
break;
}
if($start->getStarttype() == 3){
array_push($sortedCourseType3, $course);
break;
}
}
}
usort($sortedCourseType1, function ($courseA, $courseB) {
$unsortedCourseA = $courseA->getStarts()->toArray();
usort($unsortedCourseA, function ($a, $b) {
return $a->getStartdatetime() > $b->getStartdatetime();
});
$unsortedCourseB = $courseB->getStarts()->toArray();
usort($unsortedCourseB, function ($c, $d) {
return $c->getStartdatetime() > $d->getStartdatetime();
});
if($unsortedCourseA[0]->getStartdatetime() < $unsortedCourseB[0]->getStartdatetime()){
return false;
}
return true;
});
foreach ($sortedCourseType1 as $course){
array_push($sortedCourseArray, $course);
}
foreach ($sortedCourseType2 as $course){
array_push($sortedCourseArray, $course);
}
foreach ($sortedCourseType3 as $course){
array_push($sortedCourseArray, $course);
}
$courses = $sortedCourseArray;
我有课程,它们有多种开始类型和开始日期。
starttype = 1 // date
starttype = 2 // on_request
starttype = 3 // continuously
所以我按开始类型对课程进行排序,然后按开始日期时间对课程进行排序。现在它产生的订单只使用开始中的第一个条目而不是最早的条目。但是,如果我在数据库上使用查询,则排序符合预期。看起来查询和数据库之间有一些 'magic'。我的问题有解决方案吗?
在我的控制器中,我设置了排序,因为我在许多示例中都找到了它
/**
* Find all courses and sort them by start type and start date
* @throws \TYPO3\CMS\Extbase\Persistence\Exception\InvalidQueryException
*/
public function findAllSorted() {
$query = $this->createQuery();
$query->setOrderings([
'starts.starttype' => QueryInterface::ORDER_ASCENDING,
'starts.startdatetime' => QueryInterface::ORDER_ASCENDING
]);
$query->matching(
$query->logicalOr([
$query->greaterThan('starts.starttype',1),
$query->greaterThan('starts.startdatetime', time())
]));
// Debug query
//$queryParser = $this->objectManager->get(\TYPO3\CMS\Extbase\Persistence\Generic\Storage\Typo3DbQueryParser::class);
//\TYPO3\CMS\Extbase\Utility\DebuggerUtility::var_dump($queryParser->convertQueryToDoctrineQueryBuilder($query)->getSQL());
//\TYPO3\CMS\Extbase\Utility\DebuggerUtility::var_dump($queryParser->convertQueryToDoctrineQueryBuilder($query)->getParameters());
return $query->execute();
}
这会产生以下查询
SELECT `tx_vendorcontinuingeducation_domain_model_course`.*
FROM `tx_vendorcontinuingeducation_domain_model_course` `tx_vendorcontinuingeducation_domain_model_course`
LEFT JOIN `tx_vendorcontinuingeducation_domain_model_start` `tx_vendorcontinuingeducation_domain_model_start` ON `tx_vendorcontinuingeducation_domain_model_course`.`uid` = `tx_vendorcontinuingeducation_domain_model_start`.`parent`
WHERE ((`tx_vendorcontinuingeducation_domain_model_start`.`starttype` > :dcValue1)
OR (`tx_vendorcontinuingeducation_domain_model_start`.`startdatetime` > :dcValue2))
AND (`tx_vendorcontinuingeducation_domain_model_course`.`sys_language_uid` IN (0,
-1))
AND (`tx_vendorcontinuingeducation_domain_model_course`.`t3ver_oid` = 0)
AND ((`tx_vendorcontinuingeducation_domain_model_course`.`deleted` = 0)
AND (`tx_vendorcontinuingeducation_domain_model_course`.`t3ver_state` <= 0)
AND (`tx_vendorcontinuingeducation_domain_model_course`.`t3ver_wsid` = 0)
AND (`tx_vendorcontinuingeducation_domain_model_course`.`t3ver_oid` = 0)
AND (`tx_vendorcontinuingeducation_domain_model_course`.`hidden` = 0)
AND (`tx_vendorcontinuingeducation_domain_model_course`.`starttime` <= 1619622660)
AND ((`tx_vendorcontinuingeducation_domain_model_course`.`endtime` = 0)
OR (`tx_vendorcontinuingeducation_domain_model_course`.`endtime` > 1619622660))
AND (((`tx_vendorcontinuingeducation_domain_model_course`.`fe_group` = '')
OR (`tx_vendorcontinuingeducation_domain_model_course`.`fe_group` IS NULL)
OR (`tx_vendorcontinuingeducation_domain_model_course`.`fe_group` = '0')
OR (FIND_IN_SET('0', `tx_vendorcontinuingeducation_domain_model_course`.`fe_group`))
OR (FIND_IN_SET('-1', `tx_vendorcontinuingeducation_domain_model_course`.`fe_group`)))))
AND (((`tx_vendorcontinuingeducation_domain_model_start`.`deleted` = 0)
AND (`tx_vendorcontinuingeducation_domain_model_start`.`t3ver_state` <= 0)
AND (`tx_vendorcontinuingeducation_domain_model_start`.`t3ver_wsid` = 0)
AND (`tx_vendorcontinuingeducation_domain_model_start`.`t3ver_oid` = 0)
AND (`tx_vendorcontinuingeducation_domain_model_start`.`hidden` = 0)
AND (`tx_vendorcontinuingeducation_domain_model_start`.`starttime` <= 1619622660)
AND ((`tx_vendorcontinuingeducation_domain_model_start`.`endtime` = 0)
OR (`tx_vendorcontinuingeducation_domain_model_start`.`endtime` > 1619622660))
AND (((`tx_vendorcontinuingeducation_domain_model_start`.`fe_group` = '')
OR (`tx_vendorcontinuingeducation_domain_model_start`.`fe_group` IS NULL)
OR (`tx_vendorcontinuingeducation_domain_model_start`.`fe_group` = '0')
OR (FIND_IN_SET('0', `tx_vendorcontinuingeducation_domain_model_start`.`fe_group`))
OR (FIND_IN_SET('-1', `tx_vendorcontinuingeducation_domain_model_start`.`fe_group`)))))
OR (`tx_vendorcontinuingeducation_domain_model_start`.`uid` IS NULL))
ORDER BY `tx_vendorcontinuingeducation_domain_model_start`.`starttype` ASC,
`tx_vendorcontinuingeducation_domain_model_start`.`startdatetime` ASC
和值
array(2 items)
dcValue1 => 1 (integer)
dcValue2 => 1619622708 (integer)
现在我替换 dcValues 并将它们复制到我的 phpMyAdmin
SELECT `tx_vendorcontinuingeducation_domain_model_course`.*
FROM `tx_vendorcontinuingeducation_domain_model_course` `tx_vendorcontinuingeducation_domain_model_course`
LEFT JOIN `tx_vendorcontinuingeducation_domain_model_start` `tx_vendorcontinuingeducation_domain_model_start` ON `tx_vendorcontinuingeducation_domain_model_course`.`uid` = `tx_vendorcontinuingeducation_domain_model_start`.`parent`
WHERE ((`tx_vendorcontinuingeducation_domain_model_start`.`starttype` > 1)
OR (`tx_vendorcontinuingeducation_domain_model_start`.`startdatetime` > 1619619086))
AND (`tx_vendorcontinuingeducation_domain_model_course`.`sys_language_uid` IN (0,
-1))
AND (`tx_vendorcontinuingeducation_domain_model_course`.`t3ver_oid` = 0)
AND ((`tx_vendorcontinuingeducation_domain_model_course`.`deleted` = 0)
AND (`tx_vendorcontinuingeducation_domain_model_course`.`t3ver_state` <= 0)
AND (`tx_vendorcontinuingeducation_domain_model_course`.`t3ver_wsid` = 0)
AND (`tx_vendorcontinuingeducation_domain_model_course`.`t3ver_oid` = 0)
AND (`tx_vendorcontinuingeducation_domain_model_course`.`hidden` = 0)
AND (`tx_vendorcontinuingeducation_domain_model_course`.`starttime` <= 1619619060)
AND ((`tx_vendorcontinuingeducation_domain_model_course`.`endtime` = 0)
OR (`tx_vendorcontinuingeducation_domain_model_course`.`endtime` > 1619619060))
AND (((`tx_vendorcontinuingeducation_domain_model_course`.`fe_group` = '')
OR (`tx_vendorcontinuingeducation_domain_model_course`.`fe_group` IS NULL)
OR (`tx_vendorcontinuingeducation_domain_model_course`.`fe_group` = '0')
OR (FIND_IN_SET('0', `tx_vendorcontinuingeducation_domain_model_course`.`fe_group`))
OR (FIND_IN_SET('-1', `tx_vendorcontinuingeducation_domain_model_course`.`fe_group`)))))
AND (((`tx_vendorcontinuingeducation_domain_model_start`.`deleted` = 0)
AND (`tx_vendorcontinuingeducation_domain_model_start`.`t3ver_state` <= 0)
AND (`tx_vendorcontinuingeducation_domain_model_start`.`t3ver_wsid` = 0)
AND (`tx_vendorcontinuingeducation_domain_model_start`.`t3ver_oid` = 0)
AND (`tx_vendorcontinuingeducation_domain_model_start`.`hidden` = 0)
AND (`tx_vendorcontinuingeducation_domain_model_start`.`starttime` <= 1619619060)
AND ((`tx_vendorcontinuingeducation_domain_model_start`.`endtime` = 0)
OR (`tx_vendorcontinuingeducation_domain_model_start`.`endtime` > 1619619060))
AND (((`tx_vendorcontinuingeducation_domain_model_start`.`fe_group` = '')
OR (`tx_vendorcontinuingeducation_domain_model_start`.`fe_group` IS NULL)
OR (`tx_vendorcontinuingeducation_domain_model_start`.`fe_group` = '0')
OR (FIND_IN_SET('0', `tx_vendorcontinuingeducation_domain_model_start`.`fe_group`))
OR (FIND_IN_SET('-1', `tx_vendorcontinuingeducation_domain_model_start`.`fe_group`)))))
OR (`tx_vendorcontinuingeducation_domain_model_start`.`uid` IS NULL))
ORDER BY `tx_vendorcontinuingeducation_domain_model_start`.`starttype` ASC,
`tx_vendorcontinuingeducation_domain_model_start`.`startdatetime` ASC
phpMyAdmin 中的排序是正确的。这是一个错误还是我该如何解决?
Slack 上的对话表明无法使用 Extbase 按 n:m 值排序。这只有在 1:1 依赖项下才有可能。
我们随后解决了它。在获得通缉课程后,我们将它们排序为数组。如果您想对其进行分页,则可以使用新的 PaginatorAPI 中的 ArrayPaginator。
$coursesArray = $courses->toArray();
$sortedCourseArray = Array();
$sortedCourseType1 = Array();
$sortedCourseType2 = Array();
$sortedCourseType3 = Array();
foreach ($coursesArray as $course) {
$starts =$course->getStarts()->toArray();
usort($starts, function ($a, $b) {
return $a->getStarttype() > $b->getStarttype();
});
foreach ($starts as $start){
if($start->getStarttype() == 1){
array_push($sortedCourseType1, $course);
break;
}
if($start->getStarttype() == 2){
array_push($sortedCourseType2, $course);
break;
}
if($start->getStarttype() == 3){
array_push($sortedCourseType3, $course);
break;
}
}
}
usort($sortedCourseType1, function ($courseA, $courseB) {
$unsortedCourseA = $courseA->getStarts()->toArray();
usort($unsortedCourseA, function ($a, $b) {
return $a->getStartdatetime() > $b->getStartdatetime();
});
$unsortedCourseB = $courseB->getStarts()->toArray();
usort($unsortedCourseB, function ($c, $d) {
return $c->getStartdatetime() > $d->getStartdatetime();
});
if($unsortedCourseA[0]->getStartdatetime() < $unsortedCourseB[0]->getStartdatetime()){
return false;
}
return true;
});
foreach ($sortedCourseType1 as $course){
array_push($sortedCourseArray, $course);
}
foreach ($sortedCourseType2 as $course){
array_push($sortedCourseArray, $course);
}
foreach ($sortedCourseType3 as $course){
array_push($sortedCourseArray, $course);
}
$courses = $sortedCourseArray;