You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

TYPO3:QueryBuilder实现NOT ISNULL与字段降序排序的方法

如何用TYPO3 QueryBuilder实现ORDER BY NOT ISNULL(changed), changed DESC

当然可以实现这个需求!你之前的写法无效,是因为TYPO3 QueryBuilder默认会把orderBy的字符串参数当成字段名处理,自动添加反引号包裹,导致生成的SQL语法错误。下面给你两种可行的解决方案:

方法一:使用表达式构建器(推荐,符合TYPO3规范)

这种方式通过QueryBuilder的表达式构建器来创建排序逻辑,既安全又能保证SQL语法正确:

use TYPO3\CMS\Core\Utility\GeneralUtility;
use TYPO3\CMS\Core\Database\ConnectionPool;

// 获取对应表的QueryBuilder
$queryBuilder = GeneralUtility::makeInstance(ConnectionPool::class)->getQueryBuilderForTable('machines');
// 获取表达式构建器
$expr = $queryBuilder->expr();

// 构建`NOT ISNULL(changed)`的等价表达式(changed IS NOT NULL)
$notChangedIsNullExpr = $expr->isNotNull('changed');

// 组装查询:先按"changed是否非空"升序(非空数据排在前面),再按changed字段降序
$statement = $queryBuilder
    ->select('uid')
    ->from('machines')
    ->orderBy($notChangedIsNullExpr, 'ASC')
    ->addOrderBy('changed', 'DESC')
    ->executeQuery();

// 获取结果(所有uid的数组)
$uids = $statement->fetchFirstColumn();

方法二:直接传入原生SQL片段(简单直接,注意安全)

如果更习惯写原生SQL片段,可以在addOrderBy中设置第三个参数$useLiteral为true,这样QueryBuilder不会对传入的字符串做转义或包裹处理:

use TYPO3\CMS\Core\Utility\GeneralUtility;
use TYPO3\CMS\Core\Database\ConnectionPool;

$queryBuilder = GeneralUtility::makeInstance(ConnectionPool::class)->getQueryBuilderForTable('machines');

$statement = $queryBuilder
    ->select('uid')
    ->from('machines')
    // 第三个参数设为true,直接使用原生SQL片段
    ->addOrderBy('NOT ISNULL(`changed`)', 'ASC', true)
    ->addOrderBy('changed', 'DESC')
    ->executeQuery();

$uids = $statement->fetchFirstColumn();

为什么之前的写法无效?

你之前的$statement->orderBy("NOT ISNULL(changed)");会被QueryBuilder解析为字段名,生成的SQL会变成ORDER BY NOT ISNULL(changed)``,这显然不符合语法规则,所以无法正确执行。

内容的提问来源于stack exchange,提问作者Maximilian Z.

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.09 19:02:49