TL; DR移动你的服务定义之下自动加载定义在services.yml
并更改WsseFactory
代码
$container
->setDefinition($providerId, new ChildDefinition(WsseProvider::class))
->setArgument('$userProvider', new Reference($userProvider))
;
充分说明。 所提供的代码中的第一个错误是服务定义预先添加了自动加载行。自动加载只会覆盖以前的定义,并会导致AuthenticationManagerInterface
失败。移动下面的定义将解决问题。另一种解决问题的方法是@yceruto和@gintko指向的别名。
但是,只有这一举动不会使代码工作,尽管你的答案。你可能没有注意到如何改变别的东西来使它工作。
第二个问题,replaceArgument
的失败与正确推测的Symfony容器编译顺序有关。订单在PassConfig
类中定义:
$this->optimizationPasses = array(array(
new ExtensionCompilerPass(),
new ResolveDefinitionTemplatesPass(),
...
$autowirePass = new AutowirePass(false),
...
));
我省略了不相关的通行证。首先生成由WsseFactory
创建的security.authentication.provider.wsse.wsse_secured
定义。然后ResolveDefinitionTemplatesPass
会发生,并会尝试更换定义的参数,提高Cannot replace arguments
例外,你有:会出现
foreach ($definition->getArguments() as $k => $v) {
if (is_numeric($k)) {
$def->addArgument($v);
} elseif (0 === strpos($k, 'index_')) {
$def->replaceArgument((int) substr($k, strlen('index_')), $v);
} else {
$def->setArgument($k, $v);
}
}
问题原因的传球将调用Definition::replaceArgument
为index_0
。由于父母定义在位置0没有任何参数,前者services.xml
也没有固定参数。 AutowirePass
尚未执行,自动生成的定义没有参数,手动定义仅具有名为$cachePool
的参数。
因此,要解决这个问题,你可以使用比较:
->setArgument(0, new Reference($userProvider)); //proposed by @yceruto
->replaceArgument('$userProvider', new Reference($userProvider)); //proposed by @gintko
->setArgument('$userProvider', new Reference($userProvider)); // by me
他们都将需要的Definition::addArgument
或Definition::setArgument
的电话,并会制定。只有一点区别: - setArgument(0, ...
无法适用于其他一些场景; - 由于语义,我喜欢->setArgument('$userProvider'
多于->replaceArgument('$userProvider'
。没有什么可以替代!
希望详细说明问题的原因现在清楚了。
PS。还有其他几个有趣的方法来解决这个问题。
修复配置了一下:
AppBundle\Security\Authentication\Provider\WsseProvider:
arguments:
0: ''
$cachePool: '@cache.app'
public: false
或一组Symfony\Component\Security\Core\User\UserProviderInterface
别名,让自动装配为你做的休息。
$container
->setDefinition($providerId, new ChildDefinition(WsseProvider::class))
// ->replaceArgument(0, new Reference($userProvider))
;
$container
->setAlias('Symfony\Component\Security\Core\User\UserProviderInterface',$userProvider)
;
您是否拉回购回来并尝试修复?因为答案中没有任何内容会影响回购的基本实施。我有一个使用FOS User Bundle的版本,但它不起作用。它已经配置好了。 –
@JakeN:请参阅我的编辑。我已经完全改变了答案。 – tukan