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