TYPO3 v9 has reached its end-of-life September 30th, 2021 and is not maintained by the community anymore. Looking for a stable version? Use the version switch on the top left.
You can order Extended Long Term Support (ELTS) here: TYPO3 ELTS.
Main Rendering Workflow¶
This is done by example. The details to steer and how to use only sub-parts of the rendering chain are explained in more detail in the following sections.
Editing a record in the backend - often from within the
List module - triggers the
EditDocumentController by routing definitions using
and handing over which record of which table should be edited. This can be an existing record, or it could be a command
to create the form for a new record. The EditDocumentController is the main logic triggered whenever
an editor changes a record!
EditDocumentController has two main jobs: Trigger rendering of one or multiple records
via FormEngine, and hand over any given data by a FormEngine
POST result over to the DataHandler
to persist stuff in the database.
The rendering part of the
EditDocumentController job splits into these parts:
Initialize main FormEngine data array using
GETdata to specify which specific record(s) should be edited.
Select which group of DataProviders should be used.
Trigger FormEngine DataCompiler to enrich the initialized data array with further data by calling all data providers specified by selected data provider group.
Hand over DataCompiler result to an entry "render container" of FormEngine and receive a result array.
FormResultCompilerwhich hands them over to the
PageRendereroutput its compiled result.
In code, this basic workflow looks like this:
$formDataGroup = GeneralUtility::makeInstance(TcaDatabaseRecord::class); $formDataCompiler = GeneralUtility::makeInstance(FormDataCompiler::class, $formDataGroup); $nodeFactory = GeneralUtility::makeInstance(NodeFactory::class); $formResultCompiler = GeneralUtility::makeInstance(FormResultCompiler::class); $formDataCompilerInput = [ 'tableName' => $table, 'vanillaUid' => (int)$theUid, 'command' => $command, ]; $formData = $formDataCompiler->compile($formDataCompilerInput); $formData['renderType'] = 'outerWrapContainer'; $formResult = $nodeFactory->create($formData)->render(); $formResultCompiler->mergeResult($formResult);
This basically means the main FormEngine concept is a two-fold process: First create an array to gather all render-relevant information, then call the render engine using this array to come up with output.
This two-fold process has a number of advantages:
The data compiler step can be regulated by a controller to only enrich with stuff that is needed in any given context. This part is supported by encapsulating single data providers in data groups, single data providers can be omitted if not relevant in given scope.
Data providing and rendering is split: Controllers could re-use the rendering part of FormEngine while all or parts of the data providers are omitted, or their data comes from "elsewhere". Furthermore, controllers can re-use the data providing part of FormEngine and output the result in an entirely different way than HTML. The latter is for instance used when FormEngine is triggered for a TCA tree by an ajax call and thus outputs a JSON array.
The code constructs behind "data providing" and "rendering" can be different to allow higher re-use and more flexibility with having the "data array" as main communication base in between. This will become more obvious in the next sections where it is shown that data providers are a linked list, while rendering is a tree.