Initial version for webcamp venlo
This commit is contained in:
parent
af48695455
commit
bc9a00601e
3 changed files with 309 additions and 3 deletions
1
.gitignore
vendored
Normal file
1
.gitignore
vendored
Normal file
|
@ -0,0 +1 @@
|
||||||
|
/Readme.pdf
|
|
@ -1,3 +0,0 @@
|
||||||
# talk-typo3-dependency-injection
|
|
||||||
|
|
||||||
An practical introduction into Dependency Injection with Symfony Dependency Injection for TYPO3.
|
|
308
Readme.rst
Normal file
308
Readme.rst
Normal file
|
@ -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_<hash>.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:
|
||||||
|
|
||||||
|
<?php
|
||||||
|
|
||||||
|
declare(strict_types=1);
|
||||||
|
|
||||||
|
namespace WerkaumMedia\ABTest\Configuration;
|
||||||
|
|
||||||
|
use Symfony\Component\DependencyInjection\Loader\Configurator\ContainerConfigurator;
|
||||||
|
|
||||||
|
return static function (
|
||||||
|
ContainerConfigurator $containerConfigurator
|
||||||
|
) {
|
||||||
|
$services = $containerConfigurator
|
||||||
|
->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:
|
||||||
|
|
||||||
|
<?php
|
||||||
|
|
||||||
|
declare(strict_types=1);
|
||||||
|
|
||||||
|
namespace WerkraumMedia\ABTest\Configuration;
|
||||||
|
|
||||||
|
use Symfony\Component\DependencyInjection\Loader\Configurator\ContainerConfigurator;
|
||||||
|
use WerkraumMedia\ABTest\Events\SwitchedToVariant;
|
||||||
|
use WerkraumMedia\ABTest\MatomoTracker;
|
||||||
|
|
||||||
|
return static function (ContainerConfigurator $containerConfigurator) {
|
||||||
|
$services = $containerConfigurator
|
||||||
|
->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:
|
||||||
|
|
||||||
|
<?php
|
||||||
|
|
||||||
|
declare(strict_types=1);
|
||||||
|
|
||||||
|
namespace WerkraumMedia\ThueCat;
|
||||||
|
|
||||||
|
use Symfony\Component\DependencyInjection\ContainerBuilder;
|
||||||
|
use Symfony\Component\DependencyInjection\Loader\Configurator\ContainerConfigurator;
|
||||||
|
use WerkraumMedia\ThueCat\Domain\Import\Entity\MapsToType;
|
||||||
|
use WerkraumMedia\ThueCat\Domain\Import\Typo3Converter\Converter;
|
||||||
|
use WerkraumMedia\ThueCat\Domain\Import\UrlProvider\UrlProvider;
|
||||||
|
|
||||||
|
return function (ContainerConfigurator $container, ContainerBuilder $containerBuilder) {
|
||||||
|
$containerBuilder->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:
|
||||||
|
|
||||||
|
<?php
|
||||||
|
|
||||||
|
declare(strict_types=1);
|
||||||
|
|
||||||
|
namespace WerkraumMedia\ThueCat\DependencyInjection;
|
||||||
|
|
||||||
|
use Symfony\Component\DependencyInjection\Compiler\CompilerPassInterface;
|
||||||
|
use Symfony\Component\DependencyInjection\ContainerBuilder;
|
||||||
|
use WerkraumMedia\ThueCat\Domain\Import\Typo3Converter\Registry;
|
||||||
|
|
||||||
|
class ConverterPass implements CompilerPassInterface
|
||||||
|
{
|
||||||
|
public const TAG = 'thuecat.typo3.converter';
|
||||||
|
|
||||||
|
public function process(ContainerBuilder $container): void
|
||||||
|
{
|
||||||
|
$registry = $container->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/
|
Loading…
Reference in a new issue