我正在将Symfony集成到一个旧的应用程序中,它基于PSR-11拥有自己的依赖容器。一直在寻找将DI容器合并到Symfony使用的解决方案,但一无所获。为了让它发挥作用,我带了一个我不喜欢的“讨厌”的解决方案。
我创造了这门课。它在其中创建一个旧DI容器的实例:
class OldAppServiceFactory
{
private ContainerInterface $container;
public function __construct()
{
$this->container = OldContainerFactory::create();
}
public function factory(string $className)
{
return $this->container->get($className);
}
}并向services.yaml添加了适当的条目。
oldapp.service_factory:
class: Next\Service\LeonContainer\LeonServiceFactory
OldApp\Repository\Repository1:
factory: ['@oldapp.service_factory', 'factory']
arguments:
- 'OldApp\Repository\Repository1'
OldApp\Repository\Repository2:
factory: ['@oldapp.service_factory', 'factory']
arguments:
- 'OldApp\Repository\Repository2'
OldApp\configuration\ConfigurationProviderInterface:
factory: ['@oldapp.service_factory', 'factory']
arguments:
- 'OldApp\configuration\ConfigurationProviderInterface'使用上面的黑客,将这些类放到服务类构造函数中可以工作。不幸的是,它看起来很糟糕,如果用更多的这些存储库来扩展它将会很痛苦(特别是当有50个存储库的时候)。在services.yaml中能实现这样的目标吗?
OldApp\Repository\:
factory: ['@oldapp.service_factory', 'factory']
arguments:
- << PASS FQCN HERE >>这将使我在services.yaml中只为旧应用程序的单个名称空间留出一个条目。
但是,也许我的问题还有其他的解决办法?一直在尝试配置Kernel.php和prepareContainer(...)方法,但由于旧的依赖项位于返回数组的一个PHP文件中,所以我也什么也没有完成:
return array [
RepositoryMetadataCache::class => static fn () => RepositoryMetadataCache::createFromCacheFile(),
EntityCollection::class => autowire(EntityCollection::class),
'Model\Repository\*' => static function (ContainerInterface $container, RequestedEntry $entry) { ... }
];发布于 2021-12-09 14:11:08
您可能可以通过自定义编译器传递来轻松地完成这一任务。
首先,通过加载存在的目录来标记所有旧存储库类:
OldApp\Repository\:
resource: '../src/OldApp/Repository/*'
autowire: false
autoconfigure: false
tags: ['oldapp_repository'](我认为您可能还需要将src/OldApp排除在默认的自动服务加载之外。例如:
App\:
resource: '../src/*'
exclude: '../src/{OldApp/Repository,DependencyInjection,Entity,Tests,Kernel.php}'..。但我不能百分之百确定,测试这个)。
然后创建编译器传递以遍历标记,并为每个标记定义一个工厂:
class OldAppRepositoryCompilerPass implements CompilerPassInterface
{
public function process(ContainerBuilder $container): void
{
$taggedServices = $container->findTaggedServiceIds('oldapp_repository');
foreach ($taggedServices as $serviceId => $tags) {
$definition = $container->getDefinition($serviceId);
$definition
->setFactory([new Reference('oldapp.service_factory'), 'factory'])
->addArgument($serviceId);
}
}
}在应用程序内核build()方法中添加编译器传递:
// src/Kernel.php
namespace App;
use Symfony\Component\HttpKernel\Kernel as BaseKernel;
// ...
class Kernel extends BaseKernel
{
// ...
protected function build(ContainerBuilder $container): void
{
$container->addCompilerPass(new OldAppRepositoryCompilerPass());
}
}现在不能测试这个问题,但这应该会让你朝着正确的方向前进。有关其他详细信息,请查看文档:
您可以检查此示例回购上面的实现和工作地点。在这个repo上,OldApp名称空间位于App和src之外,因此不需要将它排除在自动服务加载之外。
https://stackoverflow.com/questions/70290903
复制相似问题