首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
MCP广场
社区首页 >问答首页 >对extbase TYPO3前端插件中选定类别和子类别的筛选

对extbase TYPO3前端插件中选定类别和子类别的筛选
EN

Stack Overflow用户
提问于 2018-01-22 15:28:30
回答 1查看 2.1K关注 0票数 1

我使用的是TYPO3 8.7。

我有一个扩展,允许列出事件。在列表插件设置中,编者选择类别。他希望所有具有所选类别或指定的子类别的事件都显示在前面。

我一直在阅读docs.typo3.org上的文档,并一直在查看类CategoryCollection。据我所知,这个类帮助我获取某个记录的关键字,但不帮助通过关键字选择记录。

我还想对子类别进行筛选,因为它使扩展的处理更加容易。让我们想象一下以下事件类别:

  • 课程
    • 硕士学位
    • 杆菌氏度

  • 训练
    • 内部培训
    • 外部培训

后端编辑器希望可以选择显示内部培训或所有培训,而不必显式地激活每个事件的父类别。

在extbase存储库中筛选类别及其子类别以在前端显示记录列表的正确方法是什么?

我是否必须手动实现逻辑以筛选类别和子类别?

EN

回答 1

Stack Overflow用户

回答已采纳

发布于 2018-01-22 15:28:30

我的解决方案如下:

代码语言:javascript
运行
复制
<?php
namespace Snowflake\Events\Domain\Repository;

/***************************************************************
*  Copyright notice
*
*  (c) 2018 snowflake productions gmbh <support@snowflake.ch>
*  All rights reserved
*
*  This script is part of the TYPO3 project. The TYPO3 project is
*  free software; you can redistribute it and/or modify
*  it under the terms of the GNU General Public License as published by
*  the Free Software Foundation; either version 2 of the License, or
*  (at your option) any later version.
*
*  The GNU General Public License can be found at
*  http://www.gnu.org/copyleft/gpl.html.
*
*  This script is distributed in the hope that it will be useful,
*  but WITHOUT ANY WARRANTY; without even the implied warranty of
*  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
*  GNU General Public License for more details.
*
*  This copyright notice MUST APPEAR in all copies of the script!
***************************************************************/

use TYPO3\CMS\Core\Database\ConnectionPool;
use TYPO3\CMS\Core\Database\Query\QueryBuilder;
use TYPO3\CMS\Core\Utility\GeneralUtility;
use TYPO3\CMS\Extbase\Persistence\Repository;

class EventRepository extends Repository {

    /**
     * @param $categories
     * @return array|\TYPO3\CMS\Extbase\Persistence\QueryResultInterface
     * @throws \TYPO3\CMS\Extbase\Persistence\Exception\InvalidQueryException
     */
    public function findByCategoryFilter($categories)
    {
        $categories = array_map('intval', explode(',', $categories));
        $categories = $this->expandCategories($categories);
        $uids = $this->getUidsByCategories($categories);
        if (count($uids) == 0)
            return array();
        $query = $this->createQuery();
        $query->matching(
            $query->in('uid', $uids)
        );
        return $query->execute(true);
    }

    /**
     * Return the categories and all subcategories (recursive)
     *
     * @param $categories
     * @return array
     */
    private function expandCategories($categories)
    {
        // get all categories from database
        /** @var QueryBuilder $queryBuilder */
        $queryBuilder = GeneralUtility::makeInstance(ConnectionPool::class)
            ->getQueryBuilderForTable('sys_category');
        $queryBuilder->getRestrictions()->removeAll();
        $queryBuilder
            ->select('uid', 'parent')
            ->from('sys_category');
        $allCategoriesFromDatabase = $queryBuilder->execute()->fetchAll();

        // index the categories by parent
        $categoriesByParent = array();
        foreach($allCategoriesFromDatabase as $categoryFromDatabase) {
            $categoriesByParent[(int)$categoryFromDatabase['parent']][] = (int)$categoryFromDatabase['uid'];
        }

        // expand the categories to all subcategories
        $categoriesToExpand = $categories;
        $expandedCategories = $categories;
        while(count($categoriesToExpand) > 0) {
            $currentSubCategories = array();
            foreach($categoriesToExpand as $category) {
                foreach ($categoriesByParent[$category] as $subCategory) {
                    $currentSubCategories[] = $subCategory;
                }
            }
            $categoriesToExpand = array_diff($currentSubCategories, $expandedCategories);
            $expandedCategories = array_unique(array_merge($expandedCategories, $currentSubCategories));
        }

        return $expandedCategories;
    }

    /**
     * This is a workaround because
     *
     *  $query = $this->createQuery();
     *     $query->matching(
     *     $query->contains('category', $categories)
     *  );
     *  return $query->execute(true);
     *
     * generate a useless SQL query (equals instead of in, see first WHERE condition in subquery)
     *
     * SELECT `tx_events_domain_model_event`.*
     * FROM `tx_events_domain_model_event` `tx_events_domain_model_event`
     * WHERE (`tx_events_domain_model_event`.`uid` IN
     *   (SELECT `uid_foreign`
     *   FROM `sys_category_record_mm`
     *   WHERE (`uid_local` = '1,3,5,4,6')
     *   AND ((`sys_category_record_mm`.`tablenames` = 'tx_events_domain_model_event')
     *   AND (`sys_category_record_mm`.`fieldname` = 'category'))))
     *   AND (`tx_events_domain_model_event`.`sys_language_uid` IN (0, -1))
     *   AND (`tx_events_domain_model_event`.`pid` = 161)
     *   AND ((`tx_events_domain_model_event`.`deleted` = 0)
     *   AND (`tx_events_domain_model_event`.`hidden` = 0)
     *   AND (`tx_events_domain_model_event`.`starttime` <= 1516715340)
     *   AND (
     *     (`tx_events_domain_model_event`.`endtime` = 0)
     *     OR (`tx_events_domain_model_event`.`endtime` > 1516715340)))
     *
     * @param $categories
     * @return array
     */
    private function getUidsByCategories($categories) {
        $result = array();
        /** @var QueryBuilder $queryBuilder */
        $queryBuilder = GeneralUtility::makeInstance(ConnectionPool::class)
            ->getQueryBuilderForTable('sys_category_record_mm');
        $queryBuilder->getRestrictions()->removeAll();
        $queryBuilder
            ->select('uid_foreign')
            ->from('sys_category_record_mm')
            ->where(
                $queryBuilder->expr()->andX(
                    $queryBuilder->expr()->in('uid_local', $categories),
                    $queryBuilder->expr()->eq('tablenames', '\'tx_events_domain_model_event\''),
                    $queryBuilder->expr()->eq('fieldname', '\'category\'')
                )
            );
        $records = $queryBuilder->execute()->fetchAll();
        foreach($records as $record) {
            $result[] = $record['uid_foreign'];
        }
        return $result;
    }
}
票数 2
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/48385007

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档