Building a TYPO3 extension in Extbase/Fluid
Flexform: use section for indefinitely repeatable form fields
This chapter takes on a subject that I couldn’t find a solution for in the official TYPO3 documentation. In a model of my extension I needed a set of two fields which can be filled repeatedly – but creating an additional model would have been an overload. So I thought of Flexforms. From the use of the DCE extension I knew it was possible to do what I needed – but in the documentation I couldn’t find how. I later found a post in the TYPO3 forum – but when I needed it, the website could not be loaded.
Here’s what it will look like:

So I filtered the information from ext/dce/Classes/Components/ContentElementGenerator/OutputTcaAndFlexForm.php->renderFlexformXml()
. The thing is: there’s an immense amount of nesting necessary. But see for yourself. My example is about the idea of adding several projects to a database record of my model, each project containing two simple text fields: title and description.
Note that you need <type>
and <el>
three times!
<?xml version="1.0"?>
<T3DataStructure>
<meta>
<langDisable>1</langDisable>
</meta>
<sheets>
<sheet.projects>
<ROOT>
<type>array</type>
<el>
<projects>
<title>LLL:EXT:myextension/Resources/Private/Language/locallang_be.xlf:projects.flexformTitle</title>
<type>array</type>
<section>1</section>
<el>
<projectSingle>
<title>LLL:EXT:myextension/Resources/Private/Language/locallang_be.xlf:projects.projectSingleTitle</title>
<type>array</type>
<el>
<projectTitle>
<TCEforms>
<label>LLL:EXT:myextension/Resources/Private/Language/locallang_be.xlf:projects.projectTitle</label>
<config>
<type>input</type>
<size>255</size>
<eval>trim</eval>
</config>
</TCEforms>
</projectTitle>
<projectDescription>
<TCEforms>
<label>LLL:EXT:myextension/Resources/Private/Language/locallang_be.xlf:projects.description</label>
<config>
<type>input</type>
<size>255</size>
<eval>trim</eval>
</config>
</TCEforms>
</projectDescription>>
</el>
</projectSingle>
</el>
</projects>
</el>
</ROOT>
</sheet.projects>
</sheets>
</T3DataStructure>
</T3DataStructure>
Make the data available in your Fluid template
Add a FlexformProcessing class to your extension, e.g. in /Classes/Utility
<?php
}
namespace Vendor\YourExtension\Utility;
use TYPO3\CMS\Core\Utility\GeneralUtility;
use TYPO3\CMS\Core\Service\FlexFormService;
class ProjectsProcessor
{
/**
* returns the projects (stored in the database as flexform XML) as an array for fluid
*/
public static function projectsArray($projectsXml)
{
$flexformService = GeneralUtility::makeInstance(FlexFormService::class);
$xmlArray = $flexformService->convertFlexFormContentToArray($projectsXml);
$projects = [];
if (isset($xmlArray['projects'])) {
foreach ($xmlArray['projects'] as $projectData) {
$projects[] = $projectData['projectSingle'];
}
}
return $projects;
}
}
}
Call ProjectsProcessor::projectsArray()
in your Domain Model getter function:
<?php
}
namespace Vendor\YourExtension\Domain\Model;
use Vendor\YourExtension\Utility\ProjectsProcessor;
class YourModel extends \TYPO3\CMS\Extbase\DomainObject\AbstractEntity
{
/**
* is a flexform XML string
* will be returned as an array by getApplicationProjects()
* @var string
*/
protected $projects = '';
/**
* $projects is a flexform XML string
* @return array
*/
public function getProjects()
{
return ProjectsProcessor::projectsArray($this->projects);
}
/**
* @param string $projects
+ @return void
*/
public function setProjects($projects)
{
$this->projects = $projects;
}
}
}
Call the projects in your Fluid Template:
<f:for each="{yourModel.projects}" as="project">
<h3>{project.projectTitle}</h3>
<p>{project.projectDescription>}</p>
</f:for>
</f:for>