Main rendering workflow
The details of how to control or use only sub-parts of the rendering chain are explained in more detail in the following sections.
Editing a record in the backend - usually in
Content > Layout or Content > Records modules - triggers the
Edit from routing
definitions in
Uri
and hands over records from the tables which should be edited. This could be an
existing record, or it could be a command to create a form for a new record. The
Edit is the main
logic that is triggered when an editor switches between records.
The
Edit has two
main jobs: triggering the rendering of records
via FormEngine; and handing over data from a FormEngine POST to the DataHandler
to persist in the database.
The rendering stage of the
Edit
follows these steps:
- Initialize main FormEngine data array with
POSTorGETdata which specifies which record(s) should be be edited. - Select group of DataProviders.
- Trigger FormEngine DataCompiler to enrich the data array with extra data by calling the selected DataProviders group.
- Hand over DataCompiler result to an entry "render container" in FormEngine and receive back a result array.
- Convert the raw result array into a
FormDTO usingResult Form.Result Factory - Use
Formto pass assets such as CSS, JavaScript and labels to theResult Handler PageRenderer - The
Pageoutputs the compiled result.Renderer
The controller does two distinct things here. First, it initializes a data array which is enriched by data providers from FormEngine that add all the information needed for the rendering stage. This data array is then passed onto FormEngine rendering to produce a result array containing all the HTML, CSS and JavaScript.
In code, the basic workflow looks like this:
<?php
declare(strict_types=1);
namespace MyVendor\MyExtension;
use TYPO3\CMS\Backend\Form\FormDataCompiler;
use TYPO3\CMS\Backend\Form\FormDataGroup\TcaDatabaseRecord;
use TYPO3\CMS\Backend\Form\FormResult;
use TYPO3\CMS\Backend\Form\FormResultFactory;
use TYPO3\CMS\Backend\Form\FormResultHandler;
use TYPO3\CMS\Backend\Form\NodeFactory;
final class SomeClass
{
public function __construct(
private readonly TcaDatabaseRecord $formDataGroup,
private readonly FormDataCompiler $formDataCompiler,
private readonly NodeFactory $nodeFactory,
private readonly FormResultFactory $formResultFactory,
private readonly FormResultHandler $formResultHandler,
) {}
/**
* @throws \TYPO3\CMS\Backend\Form\Exception
*/
public function someMethod(string $request, string $table, int $theUid, string $command): string
{
$formDataCompilerInput = [
'request' => $request, // the PSR-7 request object
'tableName' => $table,
'vanillaUid' => $theUid,
'command' => $command,
];
$formData = $this->formDataCompiler->compile($formDataCompilerInput, $this->formDataGroup);
$formData['renderType'] = 'outerWrapContainer';
/** @var array $rawFormResult */
$rawFormResult = $this->nodeFactory->create($formData)->render();
// Convert the raw result array into a FormResult object
/** @var FormResult $formResult */
$formResult = $this->formResultFactory->create($rawFormResult);
// Use FormResultHandler to pass collected assets (JS, CSS, labels) to PageRenderer
$this->formResultHandler->addAssets($formResult);
// Form HTML markup is accessible in the FormResult DTO
return $formResult->html;
}
}
Deprecated since version 14.2
The class
\TYPO3\ has been
deprecated. See Deprecation: #109230 - FormResultCompiler.
Basically, behind the FormEngine concept is a 2-step process: first create an array to gather all rendering-relevant information, then call the rendering engine using this array to produce output.
This 2-step process has a number of advantages:
- The data compiler step can be modified by controller to only enrich the array with data relevant to the context. Data providers are encapulated into groups so that individual data providers can be omitted if not relevant in a given scope.
- Data providing and rendering is split. Controllers can use the rendering stage of FormEngine even if all or parts of the data providers are omitted or their data comes from "elsewhere". Controllers can use the data provider stage of FormEngine and then output the result in an entirely different way than HTML, for example, for a TCA tree by an Ajax call which outputs a JSON array.
- The functionality behind "data providing" and "rendering" can be modified to promote higher re-use and more flexibility, with only the "data array" as the main communication between them. This will become more obvious in the next sections which show that data providers are a linked list and rendering is a tree.