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;