TYPO3 QueryBuilder 多个 JOIN,但出现“别名不唯一”错误

问题描述 投票:0回答:2

使用 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 给定的别名“

gb
”在 FROM 和 JOIN 子句表中不是唯一的。目前注册的别名有:
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 中的别名。但这对我不起作用。

有任何提示、想法或更好的东西吗?

typo3 extbase
2个回答
0
投票

所有联接实际上都是与 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();

0
投票

TBH 我还没有测试你的代码,但你的代码看起来相当不错,而不是关于异常消息的问题本身。

由于对程序和代码的经验和了解,异常消息:

Doctrine\DBAL\Query\QueryException 给定的别名“gb”不唯一 在 FROM 和 JOIN 子句表中。当前注册的别名是: fe_users、gb、f.

告诉我们,有人尝试重用已使用的别名。

出现此异常信息的常见情况是:

  1. 别名可重复用于另一个连接或 from 子句
  2. QueryBuilder 实例及其内部部件被重用。

阅读提供的代码,我会排除

(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()) 按预期工作:

第一次可以,第二次就不行了。由于没有深入了解完整的代码实现,我敢打赌这里会出现未识别的执行混乱。

© www.soinside.com 2019 - 2024. All rights reserved.