Commit ddc53073 authored by Benjamin Franzke's avatar Benjamin Franzke Committed by Helmut Hummel
Browse files

[DOCS] Recommend $container->hasDefinition() for optional dependencies

ExtensionManagementUtility() usage in Services.php has never been an
intended usage, but was technically possible in TYPO3 v10 as a side
effect of runtime activated packages, and therefore got documented in
example code.

Container builds should generally be stateless and should only take
explicit service configuration and ContainerBuilder compile time
state into account. Therefore conditional service registration should
only use compile time container state, which can be achieved with:
ContainerBuilder->hasDefinition(ClassNameOfOptionalDependency::class)

Resolves: #95359
Related: #95358
Releases: master, 10.4
Change-Id: I36073e9600a636d4b65f246e27109883e2dc80a1
Reviewed-on: https://review.typo3.org/c/Packages/TYPO3.CMS/+/71272

Tested-by: core-ci's avatarcore-ci <typo3@b13.com>
Tested-by: Chris Müller's avatarChris Müller <typo3@krue.ml>
Tested-by: default avatarJörg Bösche <typo3@joergboesche.de>
Tested-by: Helmut Hummel's avatarHelmut Hummel <typo3@helhum.io>
Reviewed-by: Chris Müller's avatarChris Müller <typo3@krue.ml>
Reviewed-by: default avatarJörg Bösche <typo3@joergboesche.de>
Reviewed-by: Helmut Hummel's avatarHelmut Hummel <typo3@helhum.io>
parent 6dbe94b6
......@@ -231,9 +231,14 @@ This is not intended for integrators but developers only, as this involves PHP e
The typical use case should be solved via :file:`Services.yaml`.
But for more complex situations, it is possible to register widgets via :file:`Services.php`.
Even if :file:`Services.php` contains PHP, it is only executed during compilation of the dependency injection container.
Therefore, it is not possible to check for runtime information like URLs, Users, etc..
Therefore, it is not possible to check for runtime information like URLs, users, configuration or packages.
Instead, this approach can be used to register widgets if certain extensions are enabled.
Instead, this approach can be used to register widgets only if their service dependencies are available.
The :php:`ContainerBuilder` instance provides a method :php:`hasDefinition()`
that may be used to check for optional dependencies.
Make sure to declare the optional dependencies in :file:`composer.json` and :php:`ext_emconf.php` as
suggested extensions to ensure packages are ordered correctly in order for
services to be registered with deterministic ordering.
The following example demonstrates how a widget can be registered via :file:`Services.php`:
......@@ -250,12 +255,12 @@ The following example demonstrates how a widget can be registered via :file:`Ser
use Symfony\Component\DependencyInjection\ContainerBuilder;
use Symfony\Component\DependencyInjection\Loader\Configurator\ContainerConfigurator;
use Symfony\Component\DependencyInjection\Reference;
use TYPO3\CMS\Core\Utility\ExtensionManagementUtility;
use TYPO3\CMS\Report\Status;
return function (ContainerConfigurator $configurator, ContainerBuilder $containerBuilder) {
$services = $configurator->services();
if (ExtensionManagementUtility::isLoaded('reports')) {
if ($containerBuilder->hasDefinition(Status::class)) {
$services->set('widgets.dashboard.widget.exampleWidget')
->class(ExampleWidget::class)
->arg('$view', new Reference('dashboard.views.widget'))
......@@ -275,7 +280,8 @@ The following example demonstrates how a widget can be registered via :file:`Ser
};
Above example will register a new widget called ``widgets.dashboard.widget.exampleWidget``.
The widget is only registered, in case the extension "reports" is enabled.
The widget is only registered, in case the extension "reports" is enabled, which
results in the availablity of the :php:`TYPO3\CMS\Report\Status` during container compile time.
Configuration is done in the same way as with :file:`Services.yaml`, except a PHP API is used.
The :php:`new Reference` equals to :yaml:`@` inside the YAML, to reference another service.
......
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment