diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..63928d2 --- /dev/null +++ b/.gitignore @@ -0,0 +1 @@ +/Readme.pdf diff --git a/README.md b/README.md deleted file mode 100644 index c1bfdb7..0000000 --- a/README.md +++ /dev/null @@ -1,3 +0,0 @@ -# talk-typo3-dependency-injection - -An practical introduction into Dependency Injection with Symfony Dependency Injection for TYPO3. \ No newline at end of file diff --git a/Readme.rst b/Readme.rst new file mode 100644 index 0000000..835a5c8 --- /dev/null +++ b/Readme.rst @@ -0,0 +1,308 @@ +Talk TYPO3 Dependency Injection +=============================== + +A practical introduction into Dependency Injection with Symfony Dependency Injection for TYPO3. + +.. contents:: + :local: + +What is Dependency Injection +---------------------------- + +- Our code has dependencies (E.g. Controller → View, Controller → Repository) + +- Inversion of control (ask others to inject dependencies) + +- Allow configuration of dependencies + +- Do yourself a favour and use interfaces + +- Used to connect pieces of code (E.g. event listener, commands, …) + +Flow +---- + +TYPO3 will: + +1. Check all ``Services.yaml`` and ``Services.php`` files once + +2. Use Symfony Dependency Injection once + +3. To build a psr/container (PSR-11) once + +4. Then load the psr/container on consecutive calls + +5. Use psr/container to fetch concrete implementations + +The generated code (Container) is stored at: +``var/cache/code/di/DependencyInjectionContainer_.php`` + +Usage within TYPO3 +------------------ + +Injection +^^^^^^^^^ + +A consumer needs dependencies. + +- Injection via ``__construct()`` + +- Injection via ``inject*()`` method + +- Injection via ``@required`` annotated method + +See: https://docs.typo3.org/m/typo3/reference-coreapi/main/en-us/ApiOverview/DependencyInjection/Index.html#constructor-injection + +Manually create instances +^^^^^^^^^^^^^^^^^^^^^^^^^ + +Always use ``GeneralUtility::makeInstance()``. + +- 0 arguments will ask the container + +- Requested service needs to be public + +Public services +^^^^^^^^^^^^^^^ + +Prevent them! + +Mark as public when TYPO3 forces you to do so. + +See: https://docs.typo3.org/m/typo3/reference-coreapi/main/en-us/ApiOverview/DependencyInjection/Index.html#what-to-make-public + +The Services.yaml +----------------- + +Basic example if you prefer YAML: + +.. code-block:: yaml + :linenos: + + services: + _defaults: + autowire: true + autoconfigure: true + public: false + + DanielSiepmann\Tracking\: + resource: '../Classes/*' + +The Services.php +----------------- + +Basic example if you prefer PHP: + +.. code-block:: php + :linenos: + + services() + ->defaults() + ->autowire() + ->autoconfigure() + ; + + $services->load('WerkraumMedia\\ABTest\\', '../Classes/'); + }; + +Concrete Examples +----------------- + +Injecting Query Builder +^^^^^^^^^^^^^^^^^^^^^^^ + +.. code-block:: yaml + :linenos: + + services: + _defaults: + autowire: true + autoconfigure: true + public: false + + DanielSiepmann\Tracking\: + resource: '../Classes/*' + + querybuilder.tx_tracking_pageview: + class: 'TYPO3\CMS\Core\Database\Query\QueryBuilder' + factory: + - '@TYPO3\CMS\Core\Database\ConnectionPool' + - 'getQueryBuilderForTable' + arguments: + - 'tx_tracking_pageview' + + DanielSiepmann\Tracking\Domain\Repository\Pageview: + public: true + arguments: + - '@querybuilder.tx_tracking_pageview' + +See: https://git.daniel-siepmann.de/danielsiepmann/tracking/src/branch/main/Configuration/Services.yaml + +Event Listener +^^^^^^^^^^^^^^ + +.. code-block:: php + :linenos: + + services() + ->defaults() + ->autowire() + ->autoconfigure() + ; + + $services->load('WerkraumMedia\\ABTest\\', '../Classes/'); + + $services->set(MatomoTracker::class)->tag('event.listener', [ + 'method' => 'handleVariant', + 'event' => SwitchedToVariant::class, + ]); + }; + +See: https://git.daniel-siepmann.de/Customers/abtest/src/branch/main/Configuration/Services.php + +Command +^^^^^^^ + +.. code-block:: php + :linenos: + + services: + _defaults: + autowire: true + autoconfigure: true + public: false + + DanielSiepmann\Tracking\: + resource: '../Classes/*' + + DanielSiepmann\Tracking\Command\UpdateDataCommand: + tags: + - name: 'console.command' + command: 'tracking:updatedata' + +See: https://git.daniel-siepmann.de/danielsiepmann/tracking/src/branch/main/Configuration/Services.yaml + +CompilerPass +------------ + +- Alter existing service definitions + +- E.g. add tagged classes to a registry + +- E.g. add event listeners + +- E.g. mark classes as public + +.. code-block:: php + :linenos: + + registerForAutoconfiguration(UrlProvider::class) + ->addTag(DependencyInjection\UrlProvidersPass::TAG); + $containerBuilder->addCompilerPass(new DependencyInjection\UrlProvidersPass()); + + $containerBuilder->registerForAutoconfiguration(Converter::class) + ->addTag(DependencyInjection\ConverterPass::TAG); + $containerBuilder->addCompilerPass(new DependencyInjection\ConverterPass()); + + $containerBuilder->registerForAutoconfiguration(MapsToType::class) + ->addTag(DependencyInjection\EntityPass::TAG); + $containerBuilder->addCompilerPass(new DependencyInjection\EntityPass()); + }; + + .. code-block:: php + :linenos: + + findDefinition(Registry::class); + + foreach ($container->findTaggedServiceIds(self::TAG) as $id => $tags) { + $definition = $container->findDefinition($id); + if (!$definition->isAutoconfigured() || $definition->isAbstract()) { + continue; + } + + $registry->addMethodCall('registerConverter', [$definition]); + } + } + } + +See: + +- https://git.daniel-siepmann.de/Customers/thuecat/src/branch/main/Configuration/Services.php + +- https://git.daniel-siepmann.de/Customers/thuecat/src/branch/main/Classes/DependencyInjection + +- https://symfony.com/doc/current/service_container/compiler_passes.html + +Sources +------- + +- https://docs.typo3.org/m/typo3/reference-coreapi/main/en-us/ApiOverview/DependencyInjection/Index.html + +- https://symfony.com/doc/current/components/dependency_injection.html + +- https://symfony.com/doc/current/service_container.html + +- https://usetypo3.com/dependency-injection.html + +- https://usetypo3.com/di-and-events-example.html + +- https://daniel-siepmann.de/concrete-typo3-dependency-injection-examples.html + +- https://daniel-siepmann.de/prepare-legacy-code-for-upcoming-typo3-versions.html + +- https://en.wikipedia.org/wiki/Dependency_injection + +- https://www.php-fig.org/psr/psr-11/