TYPO3 v10升级v11:仅调用inject*()方法避免构造器注入问题
TYPO3 v11表单元素依赖注入问题解决方案
问题背景
从TYPO3 v10升级到v11后,原构造器注入的表单元素类因构造参数数量不匹配报错,转而使用inject*()方法注入依赖时,又因Symfony DI容器尝试自动装配构造参数出现新错误。
可行解决方案
方案1:使用@inject属性注解(最简便)
直接在类的属性上添加@inject注解,无需修改Services.yaml,TYPO3的ObjectManager会自动完成依赖注入:
<?php use TYPO3\CMS\Form\Domain\Model\FormElements\GenericFormElement; use Vendor\Example\Service\ApiService; class ServiceSelectFormElement extends GenericFormElement { /** * @var ApiService * @inject */ protected $apiClient; public function __construct(string $identifier, string $type) { parent::__construct($identifier, $type); } }
当Form框架通过GeneralUtility::makeInstance动态传入identifier和type实例化类时,TYPO3会自动识别注解并注入ApiService,完全避开DI容器自动装配构造参数的问题。
方案2:调整Services.yaml配置,关闭自动装配
如果坚持使用inject*()方法,修改Services.yaml关闭自动装配,仅手动配置方法调用:
services: Vendor\Example\Form\Element\ServiceSelectFormElement: autowire: false calls: - method: injectApiClient arguments: $apiClient: '@Vendor\Example\Service\ApiService'
保持类的inject*()方法不变:
<?php use TYPO3\CMS\Form\Domain\Model\FormElements\GenericFormElement; class ServiceSelectFormElement extends GenericFormElement { protected $apiClient; public function injectApiClient(ApiService $apiClient): void { $this->apiClient = $apiClient; } public function __construct(string $identifier, string $type) { parent::__construct($identifier, $type); } }
TYPO3的GeneralUtility::makeInstance在实例化类时,会根据配置自动调用injectApiClient方法注入依赖,不会尝试处理构造参数。
方案3:手动触发依赖注入(自定义实例化场景)
如果是你手动实例化表单元素,可在实例化后调用ObjectManager的依赖注入方法:
use TYPO3\CMS\Core\Utility\GeneralUtility; use TYPO3\CMS\Extbase\Object\ObjectManagerInterface; // 实例化表单元素 $element = GeneralUtility::makeInstance(ServiceSelectFormElement::class, $identifier, $type); // 手动触发依赖注入 $objectManager = GeneralUtility::makeInstance(ObjectManagerInterface::class); $objectManager->injectDependencies($element);
原理说明
TYPO3 v11中,表单元素属于动态实例化类,需要传入运行时确定的identifier和type参数,这类类不适合交给Symfony DI容器自动装配(容器无法预先得知动态参数值)。而TYPO3原生的@inject注解或inject*()方法,由ObjectManager在类实例化后处理依赖注入,完美适配动态参数的场景。
内容的提问来源于stack exchange,提问作者cweiske
相关产品推荐
相关产品推荐

