我正在將 Symfony 集成到一個較舊的應用程式中,該應用程式具有基于 PSR-11 的自己的依賴項容器。一直在尋找將 DI 容器合并到 Symfony 使用的容器的解決方案,但一無所獲。為了讓它發揮作用,我帶來了一個我不喜歡的“hacky”解決方案。
我創建了這個類。它在其中創建了一個舊 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) { ... }
];
uj5u.com熱心網友回復:
您可以使用自定義編譯器傳遞輕松完成此操作。
首先通過加載它們存在的目錄來標記所有舊的存盤庫類:
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}'
...但我不是 100% 確定,測驗這個)。
然后創建一個編譯器傳遞來遍歷標簽并為每個標簽定義一個工廠:
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命名空間在Appand之外src,因此無需將其從自動服務加載中排除。
轉載請註明出處,本文鏈接:https://www.uj5u.com/qukuanlian/380551.html
標籤:php symfony 依赖注入 symfony 依赖注入
