首页 > 解决方案 > TYPO3 9.5 存储库查询以获取具有多个 sys_categories 的元素

问题描述

我试图弄清楚如何编写以下查询来获取一些具有多个类别的元素。

$query->matching(
    $query->logicalAnd(
        [
            // the following 4 lines are the problem lines
            $query->logicalAnd(
                $query->in('categories.uid', $categories),
                $query->in('categories.uid', $countryCategories)
            ),
            // $query->in('categories.uid', $categories),
            // $query->in('categories.uid', $countryCategories),

            $query->logicalOr(
                [
                    $query->equals('is_pinned', 0),
                    $query->lessThan('pinned_until', time())
                ]
            ),
        ]
    )
);

这个想法是获取categories.uid匹配至少一个 uid in$categories和至少一个 in的元素$countryCategories$categories和都是$countryCategories用类别 uid 填充的数组。

查询工作正常,直到插入第二行$query->in('categories.uid' [...]。一旦插入第二行,查询结果就为空。这可能是查询中的错误,但我和我的同事都找不到有效的解决方案。

在搜索时,我发现了 sql UNION,这是我以前从未使用过的,但我猜想如果我必须编写语句而不是构建查询,这将是可行的方法。

我想知道的是是否可以使用“查询构建器”获取元素,或者是否真的需要编写语句?如果查询生成器有解决方案,您可以为我指出吗?如果不是,我将如何构建查询以UNION根据需要获取元素?

如果有不清楚的地方,请不要犹豫,我会尝试进一步说明。谢谢。


编辑

我们也调试了查询,我直接在 phpmyadmin 中执行了它。它在没有“ AND (sys_category.uid IN ( 41, 2 ))”的情况下工作,但结果是空的。以下是调试后的查询:

SELECT `tx_gijakobnews_domain_model_news`.* 
 FROM `tx_gijakobnews_domain_model_news` `tx_gijakobnews_domain_model_news` 
    LEFT JOIN `sys_category_record_mm` `sys_category_record_mm` ON ( `tx_gijakobnews_domain_model_news`.`uid` = `sys_category_record_mm`.`uid_foreign`)  AND (( `sys_category_record_mm`.`tablenames` = 'tx_gijakobnews_domain_model_news') AND ( `sys_category_record_mm`.`fieldname` = 'categories'))  
    LEFT JOIN `sys_category` `sys_category` ON `sys_category_record_mm`.`uid_local` = `sys_category`.`uid` 

    WHERE ((
            (`sys_category`.`uid` IN ( 15, 17, 10, 11, 12, 16, 13, 14 ))
            ////// this following line is where the problem begins
            AND (`sys_category`.`uid` IN ( 41, 2 ))
    )
/////////// the following lines are additional restrictions
/////////// which have no influence on the problem
        AND ((`tx_gijakobnews_domain_model_news`.`is_pinned` = 0) OR ( `tx_gijakobnews_domain_model_news`.`pinned_until` < 1560867383))
    )
 AND ( `tx_gijakobnews_domain_model_news`.`sys_language_uid` IN ( 0, -1) )  
 AND ( `tx_gijakobnews_domain_model_news`.`pid` = 31)  
 AND ( ( `tx_gijakobnews_domain_model_news`.`deleted` = 0)  
 AND ( `tx_gijakobnews_domain_model_news`.`t3ver_state` <= 0)  
 AND ( `tx_gijakobnews_domain_model_news`.`pid` <> -1)  
 AND ( `tx_gijakobnews_domain_model_news`.`hidden` = 0)  
 AND ( `tx_gijakobnews_domain_model_news`.`starttime` <= 1560867360)  
 AND ( ( `tx_gijakobnews_domain_model_news`.`endtime` = 0)  
 OR ( `tx_gijakobnews_domain_model_news`.`endtime` > 1560867360) ) )  
 AND ( ( ( `sys_category`.`deleted` = 0)  
 AND ( `sys_category`.`t3ver_state` <= 0)  
 AND ( `sys_category`.`pid` <> -1)  
 AND ( `sys_category`.`hidden` = 0)  
 AND ( `sys_category`.`starttime` <= 1560867360)  
 AND ( ( `sys_category`.`endtime` = 0)  
 OR ( `sys_category`.`endtime` > 1560867360) ) )  
 OR ( `sys_category`.`uid` 
 IS NULL) )  
 ORDER BY `tx_gijakobnews_domain_model_news`.`publish_date` DESC

如果缺少括号,我可能在格式化时意外删除了它...

标签: mysqltypo3typo3-9.x

解决方案


我认为问题在于 where 子句是按“每行”应用的。

含义如果您有如下查询(基于您的查询):

SELECT *
FROM news
LEFT JOIN sys_category_record_mm mm
  ON (news.uid = mm.uid_foreign) /* AND (...) */
LEFT JOIN sys_category
  ON mm.uid_local = sys_category.uid
WHERE
  sys_category.uid IN (1,2,3)
  AND sys_category.uid IN (4,5,6)

您可能有一个新闻条目,即类别 1 和类别 4。但结果集将是两个不同的行:

news.uid | sys_category.uid
1        | 1
1        | 4

并且 WHERE 子句将它们都过滤掉,因为 sys_category.uid 不是单独(1, 2, 3)(4, 5, 6) 中的每一行。

在 SQL 级别上执行此操作的方法可能是对 sys_category 进行两次连接。但我不相信(相当简单的)extbase 查询生成器是可能的。

编辑:

作为一种解决方案,您可以使用$query->statement()允许使用自定义 sql 查询的方法。

$result = $query->statement('SELECT news.* FROM news');

https://docs.typo3.org/m/typo3/book-extbasefluid/master/en-us/6-Persistence/3-implement-individual-database-queries.html


推荐阅读