Using Fluid in TYPO3
Here are some examples of how Fluid can be used in TYPO3:
- Create a template (theme) using a combination of TypoScript FLUIDTEMPLATE and Fluid. Check out the TYPO3 site package tutorial which walks you through the creation of a sitepackage extension.
- Create a custom content element type in addition to the already existing content elements TYPO3 supplies.
- Extbase-based controllers have a default Fluid
view in
$this->view. - Use Fluid to create emails using the TYPO3 Mail API.
- Use Fluid in backend modules, either with or without Extbase.
- Use the generic view factory to create a Fluid view.
Changed in version 14.0
These classes were marked as deprecated in TYPO3 v13.3 and have been removed in v14:
\TYPO3\CMS\ Fluid\ View\ Standalone View \TYPO3\CMS\ Fluid\ View\ Template View \TYPO3\CMS\ Fluid\ View\ Abstract Template View \TYPO3\CMS\ Extbase\ Mvc\ View\ View Resolver Interface \TYPO3\CMS\ Extbase\ Mvc\ View\ Generic View Resolver
ViewHelper namespaces
Defining global Fluid namespaces
New in version 14.1
The extension-level configuration file Configuration/
registers and extends global Fluid namespaces. Previously,
the configuration
$GLOBALS
was used.
For example, we can define two global namespaces with the identifiers 'myext' and 'mycmp':
<?php
return [
'myext' => ['MyVendor\\MyExtension\\ViewHelpers'],
'mycmp' => ['MyVendor\\MyExtension\\Components'],
];
Assuming you have defined a Fluid component in
EXT:
then you can access the Button component via
<mycmp:button title="{title}" teaser="{teaser}" />
It is possible to override ViewHelpers that are in another extension. This is
done by TYPO3 reading and merging Configuration/
files in loaded extensions in the usual loading order. Loading order can
be changed by declaring dependencies in composer.
(and possibly ext_emconf.php). In other words, if an extension registers a
namespace that has already been registered by another extension, Fluid will merge
the namespaces.
Example (my_extension2 depends on my_extension1):
<?php
return [
'myext' => ['MyVendor\\MyExtension1\\ViewHelpers'],
];
<?php
return [
'myext' => ['MyVendor\\MyExtension2\\ViewHelpers'],
];
This results in namespace definition:
[
'myext' => [
'MyVendor\\MyExtension1\\ViewHelpers',
'MyVendor\\MyExtension2\\ViewHelpers',
],
];
The processing order is in reverse, which means that
<myext: would first check for
EXT:, and then
fall back to EXT:.
Importing Fluid namespaces locally
Say you have defined a Fluid component in
EXT:.
Instead of defining the Fluid namespace globally you can specify
the Fluid namespace like this:
<html
xmlns:my="http://typo3.org/ns/MyVendor/MyExtension/Components"
data-namespace-typo3-fluid="true"
>
<my:button title="{title}" teaser="{teaser}"/>
The namespace here is 'my'. For further information visit ViewHelper namespaces in Fluid explained.
Using the generic view factory (ViewFactoryInterface)
New in version 13.3
Class
\TYPO3\ has been added as a
generic view factory interface to create views that return an instance of
\TYPO3\. This implements the "V" of "MVC"
in a generic way and is used throughout the TYPO3 core.
You can inject an instance of the
\TYPO3\ to create an instance of a
\TYPO3\ where you need one.
Note
Extbase-based controllers create a view
instance based on this factory by default and which is accessible as
$this->view.
<?php
namespace MyVendor\MyExtension\Controller;
use Psr\Http\Message\ServerRequestInterface;
use TYPO3\CMS\Core\View\ViewFactoryData;
use TYPO3\CMS\Core\View\ViewFactoryInterface;
final readonly class MyController
{
public function __construct(
private ViewFactoryInterface $viewFactory,
) {}
public function myAction(ServerRequestInterface $request): string
{
$viewFactoryData = new ViewFactoryData(
templateRootPaths: ['EXT:my_extension/Resources/Private/Templates'],
partialRootPaths: ['EXT:my_extension/Resources/Private/Partials'],
layoutRootPaths: ['EXT:my_extension/Resources/Private/Layouts'],
request: $request,
);
$view = $this->viewFactory->create($viewFactoryData);
$view->assign('mykey', 'myValue');
return $view->render('path/to/template');
}
}
The
View needs an instance of
\TYPO3\, which is a data object and should
therefore be created via
new.
Best practices in creating a
View
instance:
- Hand over request of type
\Psr\if possible. See Getting the PSR-7 request object.Http\ Message\ Server Request Interface - Use the tuple
$template,Root Paths $partialandRoot Paths $layoutif possible by providing an array of "base" paths likeRoot Paths 'EXT:my_ extension/ Resources/ Private/ (Templates |Partials |Layouts)' - Avoid using parameter
$templatePath And Filename - Call
renderwithout file-ending on the returned ViewInterface instance.('path/ within/ template Root Path')