使用 TYPO3 11.5.32,我尝试使用 QueryBuilder 进行选择。
$assigned = $queryBuilder
->select('fe_users.uid')
->from('fe_users')
->leftJoin(
'fe_users',
'tx_crewoffice2_domain_model_getback',
'gb',
$queryBuilder->expr()->eq(
'fe_users.uid',
$queryBuilder->quoteIdentifier('gb.frontenduser')
)
)
->leftJoin(
'gb',
'tx_crewoffice2_domain_model_festival',
'f',
$queryBuilder->expr()->eq(
'gb.festival',
$queryBuilder->quoteIdentifier('f.uid')
)
)
->where(
$queryBuilder->expr()->and(
$queryBuilder->expr()->inSet(
'fe_users.usergroup',
$queryBuilder->createNamedParameter($crewgroup_uid, Connection::PARAM_INT)
),
$queryBuilder->expr()->eq(
'gb.festival',
$queryBuilder->createNamedParameter($festival_uid, Connection::PARAM_INT)
)
)
)
->executeQuery()
->fetchAll();
这会引发错误
Doctrine\DBAL\Query\QueryException 给定的别名“
”在 FROM 和 JOIN 子句表中不是唯一的。目前注册的别名有:gb
、fe_users
、gb
。f
但是生成的语句 ($queryBulder->getSQL()) 按预期工作:
SELECT `fe_users`.`uid`
FROM `fe_users`
LEFT JOIN `tx_crewoffice2_domain_model_getback` `gb`
ON (`fe_users`.`uid` = `gb`.`frontenduser`)
AND ((`gb`.`deleted` = 0)
AND (`gb`.`hidden` = 0)
AND (`gb`.`starttime` <= 1700213760)
AND ((`gb`.`endtime` = 0) OR (`gb`.`endtime` > 1700213760)))
LEFT JOIN `tx_crewoffice2_domain_model_festival` `f`
ON (`gb`.`festival` = `f`.`uid`)
AND ((`f`.`deleted` = 0)
AND (`f`.`hidden` = 0)
AND (`f`.`starttime` <= 1700213760)
AND ((`f`.`endtime` = 0) OR (`f`.`endtime` > 1700213760)))
WHERE
(FIND_IN_SET(1, `fe_users`.`usergroup`))
AND (`gb`.`festival` = 2)
AND ((`fe_users`.`deleted` = 0)
AND (`fe_users`.`disable` = 0)
AND (`fe_users`.`starttime` <= 1700213760)
AND ((`fe_users`.`endtime` = 0) OR (`fe_users`.`endtime` > 1700213760))
);
别名“gb”不能是唯一的,因为我必须在第二个 LEFT JOIN 中使用他。该查询类似于 TYPO3 QueryBuilder 文档 中的第二个示例 - 在第二个 JOIN 中使用第一个 JOIN 中的别名。但这对我不起作用。
有任何提示、想法或更好的东西吗?
所有联接实际上都是与 fe_users 联接,而不是与任何别名联接。 因此 SQL 查询是正确的,但学说代码不会生成该查询。
试试这个:
$assigned = $queryBuilder
->select('fe_users.uid')
->from('fe_users')
->leftJoin(
'fe_users',
'tx_crewoffice2_domain_model_getback',
'gb',
$queryBuilder->expr()->eq(
'fe_users.uid',
$queryBuilder->quoteIdentifier('gb.frontenduser')
)
)
->leftJoin(
'fe_users',
'tx_crewoffice2_domain_model_festival',
'f',
$queryBuilder->expr()->eq(
'gb.festival',
$queryBuilder->quoteIdentifier('f.uid')
)
)
->where(
$queryBuilder->expr()->and(
$queryBuilder->expr()->inSet(
'fe_users.usergroup',
$queryBuilder->createNamedParameter($crewgroup_uid, Connection::PARAM_INT)
),
$queryBuilder->expr()->eq(
'gb.festival',
$queryBuilder->createNamedParameter($festival_uid, Connection::PARAM_INT)
)
)
)
->executeQuery()
->fetchAll();
TBH 我还没有测试你的代码,但你的代码看起来相当不错,而不是关于异常消息的问题本身。
由于对程序和代码的经验和了解,异常消息:
Doctrine\DBAL\Query\QueryException 给定的别名“gb”不唯一 在 FROM 和 JOIN 子句表中。当前注册的别名是: fe_users、gb、f.
告诉我们,有人尝试重用已使用的别名。
出现此异常信息的常见情况是:
阅读提供的代码,我会排除
(1)
。这引导我们选择 (2)
。
有明确记录,QueryBuilder 实例必须 不得重复使用。而是在创建查询之前创建一个新实例。
遗憾的是,提供的代码没有显示 QueryBuilder 实例的创建。
每次构建查询之前,请在
$queryBuilder
中创建一个新的 QueryBuilder 实例。这意味着,而不是
$assigned = $queryBuilder
->select('fe_users.uid')
->from('fe_users')
// ... further query builder code
->executeQuery()
->fetchAll();
执行以下操作:
$connectionPool = GeneralUtility::makeInstance(ConnectionPool::class);
// ALWAYS create a new QueryBuilder instance before creating a instance,
// NEWER reuse a existing one. Saves from headaches.
$queryBuilder = $connectionPool->getQueryBuilderForTable('fe_users');
$assigned = $queryBuilder
->select('fe_users.uid')
->from('fe_users')
// ... further query builder code
->executeQuery()
->fetchAll();
但是生成的语句 ($queryBulder->getSQL()) 按预期工作:
第一次可以,第二次就不行了。由于没有深入了解完整的代码实现,我敢打赌这里会出现未识别的执行混乱。