Mit dieser Utility lassen sich fehlende Slugs (URL-Segmente) für die Datensätze eigener Extensions automatisiert generieren. Hilfreich zum Beispiel beim Import von Daten aus externen Quellen.

Das Beispiel ist abgeleitet von TYPO3\CMS\Install\Updates\PopulatePageSlugs und nutzt die Klasse TYPO3\CMS\Core\DataHandling\SlugHelper.

Slug Utility

<?php

namespace Vendor\Extension\Utility;

use TYPO3\CMS\Core\Utility\GeneralUtility;
use TYPO3\CMS\Core\DataHandling\SlugHelper;
use TYPO3\CMS\Core\DataHandling\Model\RecordStateFactory;
use TYPO3\CMS\Core\Database\ConnectionPool;
use TYPO3\CMS\Core\Database\Query\QueryBuilder;
use TYPO3\CMS\Core\Database\Query\Restriction\DeletedRestriction;

/**
 * SlugUtility
 */
class SlugUtility
{
    
    /**
     * Populate empty slugs in custom table
     * 
     * Inspired by TYPO3\CMS\Install\Updates\PopulatePageSlugs
     * Workspaces are not respected here!
     *
     * @param string $tableName
     * @param string $fieldName
     * @return void
     */
    public static function populateEmptySlugsInCustomTable($tableName, $fieldName)
    {
        
        /* @var $connection \TYPO3\CMS\Core\Database\Connection */
        $connection = GeneralUtility::makeInstance(ConnectionPool::class)->getConnectionForTable($tableName);
        /* @var $queryBuilder \TYPO3\CMS\Core\Database\Query\QueryBuilder */
        $queryBuilder = $connection->createQueryBuilder();
        /* @var $querBuilder \TYPO3\CMS\Core\Database\Query\QueryBuilder */
        $queryBuilder->getRestrictions()->removeAll()->add(GeneralUtility::makeInstance(DeletedRestriction::class));
        $statement = $queryBuilder
            ->select('*')
            ->from($tableName)
            ->where(
                $queryBuilder->expr()->orX(
                    $queryBuilder->expr()->eq($fieldName, $queryBuilder->createNamedParameter('')),
                    $queryBuilder->expr()->isNull($fieldName)
                )
            )
            ->addOrderBy('uid', 'asc')
            ->execute();

        $suggestedSlugs = [];
        
        $fieldConfig = $GLOBALS['TCA'][$tableName]['columns'][$fieldName]['config'];
        $evalInfo = !empty($fieldConfig['eval']) ? GeneralUtility::trimExplode(',', $fieldConfig['eval'], true) : [];
        $hasToBeUniqueInSite = in_array('uniqueInSite', $evalInfo, true);
        $hasToBeUniqueInPid = in_array('uniqueInPid', $evalInfo, true);
        $slugHelper = GeneralUtility::makeInstance(SlugHelper::class, $tableName, $fieldName, $fieldConfig);

        while ($record = $statement->fetch()) {
            $recordId = (int)$record['uid'];
            $pid = (int)$record['pid'];
            $languageId = (int)$record['sys_language_uid'];
            $pageIdInDefaultLanguage = $languageId > 0 ? (int)$record['l10n_parent'] : $recordId;
            $slug = $suggestedSlugs[$pageIdInDefaultLanguage][$languageId] ?? '';

            if (empty($slug)) {
                $slug = $slugHelper->generate($record, $pid);
            }

            $state = RecordStateFactory::forName($tableName)
                ->fromArray($record, $pid, $recordId);
            if ($hasToBeUniqueInSite && !$slugHelper->isUniqueInSite($slug, $state)) {
                $slug = $slugHelper->buildSlugForUniqueInSite($slug, $state);
            }
            if ($hasToBeUniqueInPid && !$slugHelper->isUniqueInPid($slug, $state)) {
                $slug = $slugHelper->buildSlugForUniqueInPid($slug, $state);
            }

            $connection->update(
                $tableName,
                [$fieldName => $slug],
                ['uid' => $recordId]
            );
        }
    }

}

Anwendung

<?php

use Vendor\Extension\Utility\SlugUtility;

SlugUtility::populateEmptySlugsInCustomTable('tx_extension_domain_model_test', 'slug');




Kommentare

Marco Kuprat schrieb am 23.03.2020:
Danke, genau sowas habe ich für eine eigene Extension gesucht! (CSV-Import in eigenes Model)
In der Anwendung sollte es jedoch heißen:

use Vendor\Extension\Utility\SlugUtility;

Ronald schrieb am 08.07.2020:
Nice work! But there is a small typo in the name of the method:

populateEmtpySlugsInCustomTable -> populateEmptySlugsInCustomTable

Mark schrieb am 14.09.2020:
Tolle Utility, vielen Dan k dafür!

Alex Weber schrieb am 03.11.2020:
Thanks! I have added it as an Upgrade Wizard, which works great.

Carsten schrieb am 04.06.2021:
Schönes Tool! Danke dafür!

Sven Burkert schrieb am 12.06.2021:
Hallo, danke für die Utility Klasse, diese hilft mir, um Datensätze der News-Extension und anderen, eigenen Extensions von einer älteren TYPO3 Version zu migrieren.
Allerdings beachtest du nur die Konfiguration "uniqueInSite" und "uniqueInPid", nicht aber "unique".

Daniel Kempf schrieb am 09.11.2021:
Vielen Dank für diese tolle Funktion und Klasse. Ich habe sie gut gebrauchen können.