fluidstan / typo3
TYPO3 integration for FluidStan: boots TYPO3, registers its Fluid namespaces and resolves EXT: paths
Requires
- php: ^8.2
- fluidstan/fluidstan: ^0.1
- typo3/cms-core: ^13.4 || ^14.0
- typo3/cms-fluid: ^13.4 || ^14.0
Requires (Dev)
- ergebnis/composer-normalize: ^2.47
- fluidstan-example/shop: @dev
- friendsofphp/php-cs-fixer: ^3.75
- php-parallel-lint/php-parallel-lint: ^1.4
- phpstan/phpstan: ^2.1.30
- phpstan/phpstan-deprecation-rules: ^2.0
- phpstan/phpstan-phpunit: ^2.0
- phpstan/phpstan-strict-rules: ^2.0
- phpunit/phpunit: ^11.5
- rector/rector: ^2.0
- saschaegerer/phpstan-typo3: ^2.2 || ^3.1
- shipmonk/composer-dependency-analyser: ^1.8
Suggests
None
Provides
None
Conflicts
None
Replaces
None
This package is auto-updated.
Last update: 2026-10-14 13:07:22 UTC
README
TYPO3 integration for FluidStan, the static analyser for Fluid templates and components powered by PHPStan. Developed and maintained by Flowd GmbH.
FluidStan analyses Fluid templates without rendering them and reports property paths that do not exist
on the model, values that cannot be rendered, loops over non-iterables, wrong ViewHelper and component
argument types, undefined variables, unknown slots and more. The screenshot shows the analysis of
docs/example, a small shop extension with an Extbase model and two components: a typo
in a property path, a DateTimeImmutable rendered without formatting, a file reference passed where a
number is expected, a float passed to the arguments of f:translate, a missing getter on a related
category read through an ObjectStorage, and an undefined variable. Run it yourself with
composer fluidstan:example.
This package makes FluidStan work inside a TYPO3 project:
- Boots TYPO3 in failsafe mode, without a database, so the package manager, extension paths and configuration are available while templates are parsed.
- Registers TYPO3's Fluid namespaces:
fincludesTYPO3\CMS\Fluid\ViewHelpers, and everything configured in$GLOBALS['TYPO3_CONF_VARS']['SYS']['fluid']['namespaces']is picked up. - Resolves
EXT:paths in the configuration, so templates are addressed the TYPO3 way.
Supports TYPO3 13.4 and 14 on PHP 8.2 or newer, in Composer mode.
Installation
composer require --dev fluidstan/typo3
The core package comes along as a dependency.
Configuration
fluidstan.neon in the project root, next to composer.json:
parameters: environment: FluidStan\TYPO3\Typo3Environment bootstrapFiles: - vendor/autoload.php paths: - EXT:my_site/Resources/Private/Components - EXT:my_site/Resources/Private/Templates namespaces: my: My\Site\Components\ComponentCollection tmpDir: var/cache/fluidstan phpstan: level: 8
environmentactivates this package.bootstrapFilesmust include the project's autoloader; TYPO3 is booted from it.pathstakeEXT:notation or paths relative to the configuration file.namespaceslists component collections and ViewHelper namespaces that are not registered globally in TYPO3. A component collection is given by its class name.tmpDirholds the generated code and PHPStan's cache; keep it out of version control.
Then run the analysis:
vendor/bin/fluidstan vendor/bin/fluidstan -c Build/fluidstan.neon # configuration elsewhere vendor/bin/fluidstan --error-format=json # for CI tooling
Run it where TYPO3 runs. In a Docker or DDEV setup that is the PHP container, because the boot reads
config/system/settings.php and additional.php like any other TYPO3 CLI command. No database
connection is opened.
What gets typed
-
Components declare their argument types with
f:argument; FluidStan checks every use against the PHP classes behind them, including your Extbase models, DTOs and value objects. -
Plain templates, partials and layouts have
mixedvariables unless you declare them with an annotation, which is also the way to type{settings},{data}or anything else a controller assigns:<f:comment> @var My\Site\Domain\Model\Product product @var array<string, mixed> data </f:comment>
-
ViewHelper arguments are validated against the ViewHelper's argument definitions with the rules Fluid 5 applies at runtime. ViewHelpers that take services through their constructor are instantiated without the constructor to read their definitions, which is sufficient for the core and most extensions.
Roadmap
- Typed TYPO3 variables out of the box:
{settings},{data},{page},{site},{language},{request} - Content Blocks field definitions as the type of
{data}and of content element component arguments - Partials and layouts resolved through TYPO3's template paths from site sets and TypoScript
- ViewHelper instantiation through the dependency injection container
- Extbase relations:
ObjectStorageand lazy-loading proxies unwrapped to their element types
Development
composer install # installs TYPO3 and the example extension for the test suite composer fluidstan:example # analyse docs/example composer check # everything below composer lint # syntax, composer.json, php-cs-fixer, PHPStan (max, strict, phpstan-typo3), Rector, dependency analysis composer fix # apply Rector, php-cs-fixer and composer normalize composer test # PHPUnit
Booting TYPO3 from the outside goes through SystemEnvironmentBuilder, which TYPO3 marks as internal;
the same route typo3-console and the testing framework take. CI runs the suite on PHP 8.2 to 8.5
against TYPO3 13.4 and 14.