远程捆绑软件有一个LogEntryExtension
Twig扩展类,我想覆盖它(Remote\Framework\DoctrineBundle\Twig\LogEntryExtension
)。
该捆绑包与外围产品一起注册在bundles.php
文件中...
// bundles.php
return [
...
'Remote\Framework\DoctrineBundle\RemoteFrameworkDoctrineBundle' => ['all' => true],
];
...并使用MicroKernelTrait
加载到自定义AppKernel
类中。服务也加载到该类中:
class AppKernel extends Kernel
{
use MicroKernelTrait;
...
public function registerBundles(): iterable
{
$contents = require dirname(__DIR__).'/config/bundles.php';
foreach ($contents as $class => $envs) {
if (isset($envs['all']) || isset($envs[$this->environment])) {
yield new $class();
}
}
}
protected function configureContainer(ContainerBuilder $container, LoaderInterface $loader): void
{
...
$confDir = dirname(__DIR__).'/config';
...
$loader->load($confDir.'/services.yml', 'glob');
}
}
常规配置有效,因此它不是新鲜的,其他服务也可以正常工作。这是services.yml
内部的服务配置,包括使用我们自己的覆盖远程LogEntryExtensions
:
services:
_defaults:
autowire: true
autoconfigure: true
public: public
App\:
resource: '../src/*'
exclude: '../src/{Annotation,DataFixtures,Entity,EntityTrait,Event,Exception,Form,DoctrineMigrations,Hideable,Integrator,Model,Repository,Statistic,Tag,Util}'
App\Form\:
resource: '../src/Form/{EventSubscriber,Type}'
...
# This is not necessary since autowiring is true, but i added it for completeness:
App\Twig\LogEntryExtension:
arguments: ['@doctrine.orm.entity_manager', '@translator']
# Here we overwrite the remote service:
remote_framework_doctrine.twig.logentry_extension:
public: false
autoconfigure: false
class: App\Twig\LogEntryExtension
arguments: ['@doctrine.orm.entity_manager', '@translator'] # Also normally unnecessary!
tags:
- { name: twig.extension }
我们的LogEntry
类具有以下构造函数参数:
namespace App\Twig;
use Twig\Extension\AbstractExtension;
class LogEntryExtension extends AbstractExtension
{
// private members
// Just that you know they aren't wrong!
public function __construct(EntityManagerInterface $em, TranslatorInterface $translator)
{
// Initializers
}
...
}
现在变得很有趣,远程LogEntryExtension
服务本身具有可选的构造函数参数...
use Remote\Framework\DoctrineBundle\Entity\LogEntry;
class LogEntryExtension extends \Twig_Extension
{
// members
public function __construct(ObjectManager $manager, $logEntryClass = LogEntry::class)
{
$this->manager = $manager;
$this->logRepo = $manager->getRepository($logEntryClass);
}
...
}
...但是服务定义仅指定实体管理器:
remote_framework_doctrine.twig.logentry_extension:
public: false,
class: Remote\Framework\DoctrineBundle\Twig\LogEntryExtension
arguments: [ '@doctrine.orm.entity_manager' ]
tags:
- { name: twig.extension }
对我来说,一切看起来都很好。 Symfony应该初始化我对logentry_extension
的定义,而不是远程的定义,但是现在我得到一个非常奇怪的错误...
消息:“传递给App \ Twig \ LogEntryExtension :: __ construct()的参数2必须实现接口Symfony \ Component \ Translation \ TranslatorInterface,给定字符串,在C中调用: \ Users \ Rene \ Documents \ Repos \ susi1 \ var \ cache \ dev \ Container4wi0fox \ appDevDebugProjectContainer.php行4061“
在项目容器中查看时会发现一个奇怪的调用:
/**
* Gets the public 'remote_framework_doctrine.twig.logentry_extension' shared autowired service.
*
* @return \App\Twig\LogEntryExtension
*/
protected function getRemoteFrameworkDoctrine_Twig_LogentryExtensionService()
{
return $this->services['remote_framework_doctrine.twig.logentry_extension'] =
new \App\Twig\LogEntryExtension(
${($_ = isset($this->services['doctrine.orm.default_entity_manager']) ?
$this->services['doctrine.orm.default_entity_manager'] :
$this->getDoctrine_Orm_DefaultEntityManagerService()) && false ?: '_'},
'Remote\\Framework\\DoctrineBundle\\Entity\\LogEntry'
);
}
要初始化服务,Symfony会正确使用我们的App\Twig\LogEntryExtension
类,但使用原始远程LogEntryExtension
的默认构造函数参数对其进行初始化...
我还尝试了上述服务定义的一些变体,总是得到相同的结果。
App\Twig\LogEntryExtension
服务,并使用定义的translator
参数对其进行初始化?