bie*_*ior 0 frontend typo3 slug extbase typo3-10.x
slug我的 TCA 中有字段,通常它可以工作,当通过后端> 列表模块添加时,即使我不会输入任何值,uniqueeval 也确保 slug 是唯一的,因此当我创建许多具有相同名称的行时富TYPO3后台将enshure,这将解决以独特的蛞蝓一样foo,foo-1,foo-2等荣誉!:
'slug' => [
'exclude' => true,
'label' => 'Slug',
'displayCond' => 'VERSION:IS:false',
'config' => [
'type' => 'slug',
'generatorOptions' => [
'fields' => ['name'],
'fieldSeparator' => '/',
'replacements' => [
'/' => '',
],
],
'fallbackCharacter' => '-',
'eval' => 'unique',
'default' => '',
'appearance' => [
'prefix' => \BIESIOR\Garage\UserFunctions\SlugPrefix::class . '->getPrefix'
],
],
],
Run Code Online (Sandbox Code Playgroud)
但是,当从我的表单中的new/create操作(如您所见,来自 extension_builder 的典型 Extbase CRUD)创建新对象时,例如:
public function createAction(Car $newCar)
{
$this->addFlashMessage(
'The object was created. Please be aware that this action is publicly accessible unless you implement an access check. See https://docs.typo3.org/typo3cms/extensions/extension_builder/User/Index.html',
'',
\TYPO3\CMS\Core\Messaging\AbstractMessage::WARNING);
$this->carRepository->add($newCar);
$this->redirect('list');
}
Run Code Online (Sandbox Code Playgroud)
当然 slug 是笔记集。
我的第一个想法是复制TCA type='slug'的逻辑,并使用一些自己的 JS、AJAX 和 PHP 添加此功能,但这听起来像是超载和耗时。尤其是我根本不希望用户关心 slug 部分。是否有任何简单的 API 可用于查找给定表的唯一 slug,可用于自定义操作?
注意这个问题不是关于如何用 JS 处理它,这只是概念。我想完全跳过 FE 用户的这一部分,他不需要知道 slug 是什么。就在创建一个新对象的过程中,我想获得独特的价值foo-123。
小智 7
除了 Jonas Eberles 的回答之外,这里还有另一个例子,它也尊重evalslug 字段的配置(可以是uniqueInSite,uniqueInPid或者只是unique)。
use TYPO3\CMS\Core\DataHandling\Model\RecordStateFactory;
use TYPO3\CMS\Core\DataHandling\SlugHelper;
use TYPO3\CMS\Core\Utility\GeneralUtility;
...
public function createAction(Car $newCar)
{
$this->carRepository->add($newCar);
GeneralUtility::makeInstance(\TYPO3\CMS\Extbase\Persistence\Generic\PersistenceManager::class)->persistAll();
$record = $this->carRepository->findByUidAssoc($newCar->getUid())[0];
$tableName = 'tx_garage_domain_model_car';
$slugFieldName = 'slug';
// Get field configuration
$fieldConfig = $GLOBALS['TCA'][$tableName]['columns'][$slugFieldName]['config'];
$evalInfo = GeneralUtility::trimExplode(',', $fieldConfig['eval'], true);
// Initialize Slug helper
/** @var SlugHelper $slugHelper */
$slugHelper = GeneralUtility::makeInstance(
SlugHelper::class,
$tableName,
$slugFieldName,
$fieldConfig
);
// Generate slug
$slug = $slugHelper->generate($record, $record['pid']);
$state = RecordStateFactory::forName($tableName)
->fromArray($record, $record['pid'], $record['uid']);
// Build slug depending on eval configuration
if (in_array('uniqueInSite', $evalInfo)) {
$slug = $slugHelper->buildSlugForUniqueInSite($slug, $state);
} else if (in_array('uniqueInPid', $evalInfo)) {
$slug = $slugHelper->buildSlugForUniqueInPid($slug, $state);
} else if (in_array('unique', $evalInfo)) {
$slug = $slugHelper->buildSlugForUniqueInTable($slug, $state);
}
$newCar->setSlug($slug);
$this->carRepository->update($newCar);
}
Run Code Online (Sandbox Code Playgroud)
在存储库中使用自定义查找器来获取 assoc 数组而不是$racord参数的映射对象
public function findByUidAssoc($uid)
{
$query = $this->createQuery();
$query->matching(
$query->equals('uid', $uid)
);
return $query->execute(true)[0];
}
Run Code Online (Sandbox Code Playgroud)
请注意,在执行上述代码之前,需要将记录持久化。
参考:
SlugHelper::generateSlugHelper::buildSlugForUniqueInSiteSlugHelper::buildSlugForUniqueInPidSlugHelper::buildSlugForUniqueInTable根据 Elias 和 Jonas 的回答,我创建了一个类来简化事情,特别是当你有更多模型需要处理时
\ntypo3conf/ext/sitepackage/Classes/Utility/SlugUtility.php
\n<?php\nnamespace VENDOR\\Sitepackage\\Utility; // <- to be replaced with your namespace\n\nuse TYPO3\\CMS\\Core\\Database\\Connection;\nuse TYPO3\\CMS\\Core\\Database\\ConnectionPool;\nuse TYPO3\\CMS\\Core\\DataHandling\\Model\\RecordStateFactory;\nuse TYPO3\\CMS\\Core\\DataHandling\\SlugHelper;\nuse TYPO3\\CMS\\Core\\Utility\\GeneralUtility;\n/***\n *\n * This file is part of the "Sitepackage" Extension for TYPO3 CMS.\n *\n * For the full copyright and license information, please read the\n * LICENSE.txt file that was distributed with this source code.\n *\n * (c) 2020 Marcus Biesioroff <biesior@gmail.com>\n * Concept by: Elias H\xc3\xa4u\xc3\x9fler\n * Jonas Eberle\n *\n ***/\nclass SlugUtility\n{\n /**\n * @param int $uid UID of record saved in DB\n * @param string $tableName Name of the table to lookup for uniques\n * @param string $slugFieldName Name of the slug field\n *\n * @return string Resolved unique slug\n * @throws \\TYPO3\\CMS\\Core\\Exception\\SiteNotFoundException\n */\n public static function generateUniqueSlug(int $uid, string $tableName, string $slugFieldName): string\n {\n\n /** @var Connection $connection */\n $connection = GeneralUtility::makeInstance(ConnectionPool::class)->getConnectionForTable($tableName);\n $queryBuilder = $connection->createQueryBuilder();\n\n $record = $queryBuilder\n ->select(\'*\')\n ->from($tableName)\n ->where(\'uid=:uid\')\n ->setParameter(\':uid\', $uid)\n ->execute()\n ->fetch();\n if (!$record) return false;\n\n// Get field configuration\n $fieldConfig = $GLOBALS[\'TCA\'][$tableName][\'columns\'][$slugFieldName][\'config\'];\n $evalInfo = GeneralUtility::trimExplode(\',\', $fieldConfig[\'eval\'], true);\n\n// Initialize Slug helper\n /** @var SlugHelper $slugHelper */\n $slugHelper = GeneralUtility::makeInstance(\n SlugHelper::class,\n $tableName,\n $slugFieldName,\n $fieldConfig\n );\n// Generate slug\n $slug = $slugHelper->generate($record, $record[\'pid\']);\n $state = RecordStateFactory::forName($tableName)\n ->fromArray($record, $record[\'pid\'], $record[\'uid\']);\n\n// Build slug depending on eval configuration\n if (in_array(\'uniqueInSite\', $evalInfo)) {\n $slug = $slugHelper->buildSlugForUniqueInSite($slug, $state);\n } else if (in_array(\'uniqueInPid\', $evalInfo)) {\n $slug = $slugHelper->buildSlugForUniqueInPid($slug, $state);\n } else if (in_array(\'unique\', $evalInfo)) {\n $slug = $slugHelper->buildSlugForUniqueInTable($slug, $state);\n }\n return $slug;\n }\n}\nRun Code Online (Sandbox Code Playgroud)\n在任何地方使用,例如控制器。调度程序任务、存储库等。请记住,记录应该在之前保存(可以由 Extbase 创建,或者仅使用普通 SQL 创建),只需已创建uid并且是有效的 TYPO3 记录即可。
use VENDOR\\Sitepackage\\Utility\\SlugUtility;\nuse \\TYPO3\\CMS\\Extbase\\Persistence\\Generic\\PersistenceManager;\n\n...\n\n$pageSlug = SlugUtility::generateUniqueSlug(\n 5, // int $uid UID of record saved in DB\n \'pages\', // string $tableName Name of the table to lookup for uniques\n \'slug\' // string $slugFieldName Name of the slug field\n)\n\n// or\n\n$uniqueSlug = SlugUtility::generateUniqueSlug(\n 123,\n \'tx_garage_domain_model_car\',\n \'slug\'\n);\n\n// or according to the original question, \n// if you created new model object with Extbase, \n// persist it, create unique slug with SlugUtility \n// set the slug property to the created model object and finally update\n\npublic function createAction(Car $newCar)\n{\n $this->carRepository->add($newCar);\n GeneralUtility::makeInstance(PersistenceManager::class)->persistAll();\n $uniqueSlug = SlugUtility::generateUniqueSlug(\n $newCar->getUid(),\n \'tx_garage_domain_model_car\',\n \'slug\'\n );\n if($uniqueSlug) {\n $newCar->setSlug($uniqueSlug);\n $this->carRepository->update($newCar);\n }\n $this->redirect(\'list\');\n}\n\n// no need for second call to persistAll() \n// as Extbase will call it at action\'s finalizing.\n\n// etc.\nRun Code Online (Sandbox Code Playgroud)\n