Alle kennen das Problem, man baut seinen slug um (hoffentlich nur im Testsystem) und muss hunderte Slugs neu generieren. Das ist nervig.
Ich habe hier ein Command für alle (auch dank @Franky), welches hoffentlich hilft, so etwas schnellstmöglich bereinigen zu können:
your_package/Classes/Command/UpdateSlugsForTable.php
<?php
declare(strict_types=1);
namespace VENDOR\YourPackage\Command;
use Symfony\Component\Console\Command\Command;
use Symfony\Component\Console\Helper\ProgressBar;
use Symfony\Component\Console\Input\InputArgument;
use Symfony\Component\Console\Input\InputInterface;
use Symfony\Component\Console\Input\InputOption;
use Symfony\Component\Console\Output\OutputInterface;
use TYPO3\CMS\Core\Database\Connection;
use TYPO3\CMS\Core\Database\ConnectionPool;
use TYPO3\CMS\Core\DataHandling\Model\RecordStateFactory;
use TYPO3\CMS\Core\DataHandling\SlugHelper;
use TYPO3\CMS\Core\Utility\GeneralUtility;
class UpdateSlugsForTable extends Command
{
protected function configure(): void
{
$this->setDescription('Update slug field according to TCA Parameters in a table');
$this->setHelp($this->getDescription());
$this->addArgument(
'table',
InputArgument::REQUIRED,
'Name of the table'
)
->addOption(
'updateall',
'a',
InputOption::VALUE_NONE,
'update non empty slug fields as well (refresh) - can break urls',
null
);
}
protected function execute(InputInterface $input, OutputInterface $output): int
{
$table = $input->getArgument('table');
$updateAll = $input->getOption('updateall');
if (!isset($GLOBALS['TCA'][$table])) {
$output->write('ERROR: no such table ' . $table, true);
die(1);
}
$slug = [];
$slugField = null;
foreach ($GLOBALS['TCA'][$table]['columns'] as $field => $col) {
if ($col['config']['type'] === 'slug') {
$slug = $col;
$slugField = $field;
}
}
if ($slugField === null) {
$output->writeln('<error>Table ' . $table . ' has no field of type slug configured</error>');
return Command::FAILURE;
}
/** @var Connection $connection */
$connection = GeneralUtility::makeInstance(ConnectionPool::class)
->getConnectionForTable($table);
if ($updateAll) {
$connection->update($table, [$slugField => ''], ['deleted' => '0']);
}
$where = [
'deleted' => '0',
$slugField => '',
];
$res = $connection->select(['*'], $table, $where);
$rows = $res->fetchAllAssociative();
$progressBar = new ProgressBar($output, count($rows));
$helper = GeneralUtility::makeInstance(
SlugHelper::class,
$table,
$slugField,
$slug['config'],
0
);
foreach ($rows as $row) {
$value = $helper->generate($row, $row['pid']);
$state = RecordStateFactory::forName($table)
->fromArray($row, $row['pid'], 'NEW');
$evalCodesArray = GeneralUtility::trimExplode(',', $slug['config']['eval'], true);
if (in_array('unique', $evalCodesArray, true)) {
$value = $helper->buildSlugForUniqueInSite($value, $state);
}
if (in_array('uniqueInPid', $evalCodesArray, true)) {
$value = $helper->buildSlugForUniqueInPid($value, $state);
}
$connection->update($table, [$slugField => $value], ['uid' => $row['uid']]);
$progressBar->advance();
}
$progressBar->finish();
$output->writeln('');
return Command::SUCCESS;
}
}
Das Ganze dann noch registrieren:
your_package/Configuration/Services.yaml
VENDOR\YourPackage\Command\UpdateSlugsForTable:
tags:
- name: 'console.command'
command: 'database:update:slugs'
schedulable: false
Sollte auch ohne Probleme so in v12 laufen.