I would like to calculate the slug automatically by using the parent object. Like with the pages where the parent pages are part of the slug.
In my extension I have an object hierarchy like 'journal' > 'volume' > 'issue' > 'article' etc. I want the slug to be something like:
/volume/5/issue/7/headline-of-the-article
How can this be done?
[TYPO3 v11]
To calculate a slug for your custom object you need following:
1.A path-segment field in your database. Add to your article models SQL:
path_segment varchar(255) DEFAULT '' NOT NULL
2.Add the field to the article models TCA:
'path_segment' => [
'exclude' => true,
'label' => 'URL path segment',
'l10n_mode' => 'exclude',
'config' => [
'type' => 'slug',
'generatorOptions' => [
'fields' => ['title'], // Title of your article
'fieldSeparator' => '/',
'prefixParentPageSlug' => false,
'postModifiers' => [
\VENDOR\ExtName\PostModifier\MyCoolPostModifier::class . '->modifySlug'
],
],
'fallbackCharacter' => '-',
'eval' => 'uniqueInSite',
'default' => ''
],
],
If the postmodifier does not work as described. Check out the docs. There it sais the postmodifier should be registered as a hook: https://docs.typo3.org/m/typo3/reference-tca/main/en-us/ColumnsConfig/Type/Slug/Properties/GeneratorOptions.html#confval-generatorOptions-postModifiers
3.A postmodifier class with a modifySlug method:
The method receives an parameter with the following values:
[
'slug' // ... the slug to be used
'workspaceId' // ... the workspace ID, "0" if in live workspace
'configuration' // ... the configuration of the TCA field
'record' // ... the full record to be used
'pid' // ... the resolved parent page ID
'prefix' // ... the prefix that was added
'tableName' // ... the table of the slug field
'fieldName' // ... the field name of the slug field
];
There you can load the parent objects of your article and then generate the slug. At the end return the modified slug. If you need help with that, give me a hint in the comments.
EDIT:
Here is an example postModifier that should fit your requirements:
<?php
namespace VENDOR\ExtName\PostModifier;
use VENDOR\ExtName\Domain\Repository\ArticleRepository;
use TYPO3\CMS\Core\Utility\GeneralUtility;
use TYPO3\CMS\Extbase\Object\ObjectManager;
use TYPO3\CMS\Extbase\Persistence\Generic\PersistenceManager;
class SlugPostModifier
{
public function modifySlug(array $data): string
{
// You will need the uid of the articles Record
$recordUid = $data['record']['uid'];
// To load the Object you will need the object manager and persistence manager
$objectManager = GeneralUtility::makeInstance(ObjectManager::class);
$persistenceManager = GeneralUtility::makeInstance(PersistenceManager::class);
// Instanciate your article repository and inject the persistence manager
$articleRepository = GeneralUtility::makeInstance(ArticleRepository::class, $objectManager);
$articleRepository->injectPersistenceManager($persistenceManager);
// Fetch the article object by record uid
$article = $articleRepository->findByUid($recordUid);
// Load the articles parent objects - somehow like (Depends on your models)
$issue = $article->getIssue();
$volume = $issue->getVolume();
$journal = $volume->getJournal();
// Load the path segments of the articles parent objects
$articleSlug = $data['slug'];
$issueSlug = $issue->getPathSegment();
$volumeSlug = $volume->getPathSegment();
$journalSlug = $journal->getPathSegment();
/**
* If your articles parent objects do not have path segments,
* then you could also load the title-fields.
* But be aware that you than have to do several string operations.
* Like strtolower(), str_replace() etc....
* to replace capitals letters and special characters like german umlauts i.e.
*/
return "$journalSlug/$volumeSlug/$issueSlug/$articleSlug";
}
}