TYPO3 – sys-category via typoscript und Fluid viewhelper auslesen

Im Netz findet man nicht wirklich Hilfe wenn es um das Thema TYPO3 System-Kategorien geht, die es seit der 6.2 Version im Core gibt.
Ich möchte Euch zwei Wege zeigen wie man diese einmal via typoscript auslesen kann und einmal via PHP als Viewhelper, damit wir die Categories Daten direkt im FLUID-Template verwenden können.

Hier einmal der erste Weg, via PHP / ViewHelper / Fluid:

Bindet dazu in Eure eigene Extension im Ordner diese Datei ein:
extname/Classes/ViewHelpers/SysCategoryViewHelper.php

<?php
namespace ID\Simpletemplates\ViewHelpers;

/*
 *  The MIT License (MIT)
 *
 *  Copyright (c) 2017 INGENIUMDESIGN, http://www.ingeniumdesign.de/
 *
 *  Permission is hereby granted, free of charge, to any person obtaining a copy
 *  of this software and associated documentation files (the "Software"), to deal
 *  in the Software without restriction, including without limitation the rights
 *  to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
 *  copies of the Software, and to permit persons to whom the Software is
 *  furnished to do so, subject to the following conditions:
 *
 *  The above copyright notice and this permission notice shall be included in
 *  all copies or substantial portions of the Software.
 *
 *  THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
 *  IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
 *  FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
 *  AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
 *  LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
 *  OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
 *  THE SOFTWARE.
 */

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

/*
 * <html xmlns:f="http://typo3.org/ns/TYPO3/CMS/Fluid/ViewHelpers" xmlns:id="http://typo3.org/ns/ID/Simpletemplates/ViewHelpers" data-namespace-typo3-fluid="true">
 * 
 * 
 * 
 * // get everything with parent = 1 (array would work too)
 * <id:SysCategory uid="1" byParentId="true" />
 * <f:debug>{sysCategoryDetailArray}</f:debug>
 * 
 * // by single ID
 * <id:SysCategory uid="1" />
 * <f:debug>{sysCategoryDetailArray}</f:debug>
 * 
 * // by specific IDs
 * <id:SysCategory uid="{0: 1, 1: 2, 2:3}" />
 * <f:debug>{sysCategoryDetailArray}</f:debug>
 * 
 * 
 * // everything:
 * <id:SysCategory />
 * <f:debug>{sysCategoryDetailArray}</f:debug>
 * 
 */

class SysCategoryViewHelper extends \TYPO3\CMS\Fluid\Core\ViewHelper\AbstractViewHelper {

    /**
     * @params integer $uid (CE)
     * @params string $tableCell (of sys_category)
     * @return CategorieName
     * @author INGENIUMDESIGN
     */
    public function initializeArguments() {
        /*$this->registerArgument('uid', 'integer', 'enthaelt die UID des CE', TRUE);
        $this->registerArgument('tableCell', 'string', 'enthaelt das Tabellenelement aus sys_category', TRUE);
        $this->registerArgument('table', 'string', 'enthaelt den Tabellennamen aus sys_category_record_mm', TRUE);*/
    }

    /**
    * @param mixed $uid
    * @param boolean $byParentId 
    */
    public function render($uid = null, $byParentId = false) {
        $queryBuilder = GeneralUtility::makeInstance(ConnectionPool::class)->getQueryBuilderForTable('sys_category');
        $query = $queryBuilder
            ->select('*')
            ->from('sys_category');
        
        if ($uid !== null) {
            $uid = is_array($uid) ? $uid : [$uid];
            
            $query->where(
                $queryBuilder->expr()->in(
                    $byParentId ? 'parent' : 'uid',
                    $uid
                )
            );
        }
        
        $result = $query->execute();
        $res = [];
        while ($row = $result->fetch()) {
            $res[] = $row;
        }
        
        $this->templateVariableContainer->add('sysCategoryDetailArray', $res);
    }

}

/*
 * TODO: Multilang
 */

Ich habe im Code auch schon die vorhanden Variablen beschrieben:

// get everything with parent = 1 (array would work too)
<id:SysCategory uid="1" byParentId="true" />
<f:debug>{sysCategoryDetailArray}</f:debug>

// by single ID
<id:SysCategory uid="1" />
<f:debug>{sysCategoryDetailArray}</f:debug>

// by specific IDs
<id:SysCategory uid="{0: 1, 1: 2, 2:3}" />
<f:debug>{sysCategoryDetailArray}</f:debug>

// everything:
<id:SysCategory />
<f:debug>{sysCategoryDetailArray}</f:debug>

Im Fluid Tempalte selbst, könnt Ihr nun oben den ViewHelper laden, mit folgender Code-Zeile:


<html xmlns:f="http://typo3.org/ns/TYPO3/CMS/Fluid/ViewHelpers"
 xmlns:id="http://typo3.org/ns/ID/Simpletemplates/ViewHelpers"
 data-namespace-typo3-fluid="true">

Dann könnt Ihr einen der oberen Beispiel-Fluid-Codes beliebig einbinden und via Debug die Felder auslesen.
Ich werde den ViewHelper noch weiter ausbauen und dann hier updaten.

TypoScript

Hier nun die TypoScript Version um die sys_category auszulesen:

Legt dazu einfach im typoscript-Ordner oder in einer neuen ts-Datei diesen dataProcessing Code an.

lib.contentElement {
    dataProcessing {
        999 = TYPO3\CMS\Frontend\DataProcessing\DatabaseQueryProcessor
        999 {
            if.isTrue.field = categories
            table = sys_category
            selectFields = sys_category.*
            pidInList = this
            recursive = 999
            join = sys_category_record_mm ON sys_category.uid = sys_category_record_mm.uid_local
            where.data = field:uid
            where.wrap = sys_category_record_mm.tablenames = 'tt_content' and sys_category_record_mm.uid_foreign='|'
            orderBy = sys_category.sorting
            as = categories
        }
    }
}

Wichtig ist hier aber noch, dass alle Kategorien in einem Ordner liegen.
Hier gibt es leider noch keine Lösung wenn die Kategorien in verschieden Ordner abgelegt sind.

Wenn wir nun im Fluid-Tempalte einmal den {_all} aufrufen, so sollte nun unter „categories“ alle Informationen der Kategorien erfolgen.
Wichtig ist, wir müssen Backend-Elemente auch eine Kategorie zuweisen.

Vielen Dank an @Benjamin und @Kurt

Eure Meinung zu dem Artikel ist gefragt! Schreibt mir ein Kommentar

Hat Euch der Artikel weitergeholfen oder gefallen?
Ich freue mich auf einen Blick auf meine Amazon-Wunschliste. Vielen Dank!

Hat Euch der Artikel geholfen oder gefallen?
Ich freue mich auf einen Blick auf meine Amazon-Wunschliste.
Vielen Dank!


Ich bin TYPO3 Freelancer, TYPO3-Entwickler, Web-Entwickler und Frontend-Entwickler. Ich arbeite im und für das Web seit 2004.
Mehr Infos zu der TYPO3 Internet-Agentur INGENIUMDESIGN.

Besucht auch unser TYPO3 Hilfe Forum.

Leave a Reply

Diese Website verwendet Akismet, um Spam zu reduzieren. Erfahre mehr darüber, wie deine Kommentardaten verarbeitet werden.

5 Kommentare

  1. So wie ich das verstehe, gibt dieser ViewHelper eine Category nach deren UID zurück, richtig? Ich habe einen ViewHelper geschrieben, der tatsächlich Categories eines Records zurückgibt: per Default als Array für ein record aus tt_content (warum das im {data}-Array im Template nicht standardmäßig drin ist, erschließt sich mir nicht). Aber die Tabelle kann im Aufruf geändert werden, ebenso wie eine Ausgabe als String möglich ist, mit Prefixes, definiertem Separator (default: Komma) oder eingeschlossen von einem HTML-Attribut:

    https://coding.musikinsnetz.de/typo3/fluid-viewhelpers/access-system-categories-in-content-elements-templates

    Ich dachte, das interessiert vielleicht die eine oder den anderen, da ich bei der Suche nach einer Lösung auf dieser Seite hier gelandet bin.

  2. Ich habe es nun so gelöst (Typo3 9+):
    class CatViewHelper extends \TYPO3\CMS\Fluid\Core\ViewHelper\AbstractViewHelper {

    public function initializeArguments() {
    $this->registerArgument(‚uid‘, ‚integer‘, ‚UID of category‘, true);
    $this->registerArgument(‚isChild‘, ‚boolean‘, ‚is child‘, false, false);
    }

    public function render() {
    $currentLanguageUid = intval(GeneralUtility::makeInstance(Context::class)->getPropertyFromAspect(‚language‘, ‚id‘));
    $queryBuilder = GeneralUtility::makeInstance(ConnectionPool::class)->getQueryBuilderForTable(’sys_category‘);
    if ($currentLanguageUid === 0) {
    $query = $queryBuilder
    ->select(‚uid‘, ‚t3_origuid‘, ’slug‘, ‚title‘, ’sys_language_uid‘, ‚parent‘)
    ->from(’sys_category‘)
    ->where($queryBuilder->expr()->in(’sys_category.parent‘, is_array($this->arguments[‚uid‘]) ? $this->arguments[‚uid‘] : [$this->arguments[‚uid‘]]))
    ->andWhere($queryBuilder->expr()->in(’sys_category.sys_language_uid‘, 0));
    $result = $query->execute();
    $res = [];
    while ($row = $result->fetch()) {
    $res[] = $row;
    }
    return $res;
    } else {
    if ($this->arguments[‚isChild‘]) {
    $query = $queryBuilder
    ->select(‚uid‘, ‚t3_origuid‘, ’slug‘, ‚title‘, ’sys_language_uid‘, ‚parent‘)
    ->from(’sys_category‘)
    ->where($queryBuilder->expr()->in(’sys_category.parent‘, is_array($this->arguments[‚uid‘]) ? $this->arguments[‚uid‘] : [$this->arguments[‚uid‘]]))
    ->andWhere($queryBuilder->expr()->in(’sys_category.sys_language_uid‘, $currentLanguageUid));
    $result = $query->execute();
    $res = [];
    while ($row = $result->fetch()) {
    $res[] = $row;
    }
    return $res;
    } else {
    $query = $queryBuilder
    ->select(‚t3_origuid as uid‘, ’slug‘, ‚title‘, ’sys_language_uid‘, ‚parent‘)
    ->from(’sys_category‘)
    ->where($queryBuilder->expr()->in(’sys_category.parent‘, is_array($this->arguments[‚uid‘]) ? $this->arguments[‚uid‘] : [$this->arguments[‚uid‘]]))
    ->andWhere($queryBuilder->expr()->in(’sys_category.sys_language_uid‘, $currentLanguageUid));
    $result = $query->execute();
    $res = [];
    while ($row = $result->fetch()) {
    $res[] = $row;
    }
    return $res;
    }
    }
    }

    }
    Vielleicht kann das jemand abändern

  3. bzgl. „Wichtig ist hier aber noch, dass alle Kategorien in einem Ordner liegen.
    Hier gibt es leider noch keine Lösung wenn die Kategorien in verschieden Ordner abgelegt sind.“

    In den constants könnte man eine Variable anlegen „categoriesPids = 1“ z.B. oder „categoriesPids = 1,5“
    und diese anstatt „this“ in den DP schreiben:
    pidInList = {$categoriesPids}
    Diese IDs sind ja die der Seiten oder Verzeichnisse in denen Kategorien gespeichert wurden.

    Sebastian, Du darfst ruhig meinen Namen voll ausschreiben in Deiner Zeile
    „Vielen Dank an @Benjamin und @Kurt“ oben, so in etwa:
    Vielen Dank an @Benjamin ??? und @Kurt Kunig! 😉

  4. Geddo

    Das Typoscript geht in der 8er nicht mehr :-/

  5. Guido Hache

    Ja, es gibt nicht viel im Internet zu den Kategorien. Ich stehe aktuell vor dem Problem, dass ich die Kategorien, die Dateien zugeornet sind ausgeben möchte. Diese sind zu finden in der Tabelle sys_file_metadata.
    Ich habe ein CE mit Mask erstellt und da sollen nun Dateien ausgegeben werden und dazu eben auch die zugeorneten Kategorien. Ich kann das TS von oben leider nicht entsprechend anpassen. Den Aufruf im Fluid Element stelle ich mir so vor
    .
    Hast Du vielleicht einen Tipp, wie das TS angepasst werden muss, damit ich zu der file.uid die Kategorien bekomme?

Next ArticleDie TYPO3-Gretchenfrage - wie hältst du's mit der Umsetzung?