当前位置: 首页 > 知识库问答 >
问题:

将Symfony的依赖注入(自动连接)集成到遗留应用程序中

万俟浩
2023-03-14

我有一个遗留的应用程序,它是建立在一个旧的自定义MVC框架上的,我想最终远离它。这个框架不依赖于单个前端控制器,所以大多数页面仍然有专用的php文件来调用受人尊敬的控制器,其他的是混合的php/html。我已经阅读了使用各种方法(https://symfony.com/doc/current/migration.html)将应用程序迁移到symfony,但是我对这两种方法都有问题,并且意识到我并不真正需要symfony的路由处理。

Symfony目前存在于我们的应用程序中,但仅由各种命令使用。我们所有的核心逻辑仍然在遗留应用程序中,因此Symfony可以毫无问题地访问它,因为类都在全局命名空间中。但是,问题是,遗留应用程序不能使用任何新的Symfony类,因为它不支持依赖注入。为了开始将我们的一些核心逻辑和功能转移到Symfony,需要这种能力。

理想情况下,我希望能够完成的是在容器中加载到遗留应用程序,该应用程序具有所有可用的自动连线服务。允许我在传统应用程序中访问新的基于Symfony的服务。

任何帮助都是非常感激的。

非常感谢你。

更新1

所以我尝试了@Cerad所说的,只需访问内核,因为它是全局的。我复制了引导程序。php逻辑到我的旧版应用程序的主配置(因此它加载现有的.env*文件),然后启动内核(在我的旧版配置中实例化它并调用boot)。它可以工作,我可以在php文件中引用$kernel(使用全局$kernel)并访问容器。然而,这与@Dmitry Solovov的响应一致,服务必须是公共的。

我必须将我想要的所有服务设置为公共服务吗?如果我在服务中手动定义服务。亚姆,把它设为公共的,它就行了。

但这并不理想,因为我想自动加载我的服务,因此我可以正确使用服务,而不必明确定义我希望在遗留应用程序中提供的每个服务。

在不公开服务的情况下,如何将服务注入到遗留控制器中?就像Symfony的控制器如何允许您将服务注入控制器方法一样?

多谢了。

共有2个答案

白萧迟
2023-03-14

我在所有页面上都加载了一个配置,在这里我复制了引导逻辑并加载了内核:

// ***** legacy config code above

// This probably could just be loaded using require, but kept it here for completeness
if (is_array($env = @include dirname(__DIR__).'/.env.local.php')) {
    foreach ($env as $k => $v) {
        $_ENV[$k] = $_ENV[$k] ?? (isset($_SERVER[$k]) && 0 !== strpos($k, 'HTTP_') ? $_SERVER[$k] : $v);
    }
} elseif (!class_exists(Dotenv::class)) {
    throw new RuntimeException('Please run "composer require symfony/dotenv" to load the ".env" files configuring the application.');
} else {
    // load all the .env files
    (new Dotenv(false))->loadEnv(dirname(__DIR__).'/config/.env');
}

$_SERVER += $_ENV;
$_SERVER['APP_ENV'] = $_ENV['APP_ENV'] = ($_SERVER['APP_ENV'] ?? $_ENV['APP_ENV'] ?? null) ?: 'dev';
$_SERVER['APP_DEBUG'] = $_SERVER['APP_DEBUG'] ?? $_ENV['APP_DEBUG'] ?? 'dev' == $_SERVER['APP_ENV'];
$_SERVER['APP_DEBUG'] = $_ENV['APP_DEBUG'] = (int) $_SERVER['APP_DEBUG'] || filter_var($_SERVER['APP_DEBUG'], FILTER_VALIDATE_BOOLEAN) ? '1' : '0';
// End Symfony's bootstrap

// Load Symfony's kernel
$kernel = new Kernel($_SERVER['APP_ENV'], (bool) $_SERVER['APP_DEBUG']);
$kernel->boot();

从那里,我可以访问我想要的特定服务——只要它是公开的:

global $kernel;
$service = $kernel->getContainer()->get(\App\Services\MyService::class);

让我的项目顺利运行的真正想法不是将所有服务设置为公共服务,而是创建一个遗留服务,该服务是在服务中手动定义的。yaml并设置为公共:

services:
    App\Services\Legacy\AWSLegacy:
        public: true

AWSLegacy看起来像:

namespace App\Services\Legacy;

use App\Services\AWS\S3;

class AWSLegacy
{
    /** @var S3 */
    public $s3;

    public functhtml" target="_blank">ion __construct(
        S3 $s3
    )
    {
        $this->s3 = $s3;
    }
}

这使我能够将我希望在遗留应用程序中可用的类似服务组合在一起,而无需在services.yaml中手动为每个服务创建引用并将其设置为公共。

Symfony桥接方法对我不起作用,因为我不想Symfony在我的旧应用程序中处理路由(请求和响应),我只想访问新的服务。

谢谢@Cerad和@Dmitry Solovov的帮助。

缪嘉志
2023-03-14

要独立使用依赖项注入,请执行以下操作:

  • 安装软件包:
composer require symfony/dependency-injection
  • 配置文件中定义您的服务(即src/Resources/config/services.yaml)。例:
services:
    _defaults:
        autowire: true
        autoconfigure: true
        public: false

    App\Services\MyService:
        class: App\Services\MyService
        public: true

您还可以使用服务自动导入功能https://symfony.com/doc/current/service_container.html#importing-many-services-at-once-with-resource

  • 使用以下代码编译DI容器:
use Symfony\Component\Config\FileLocator;
use Symfony\Component\DependencyInjection\ContainerBuilder;
use Symfony\Component\DependencyInjection\Loader\YamlFileLoader;

$container = new ContainerBuilder();
$loader = new YamlFileLoader($container, new FileLocator(__DIR__.'/src/Resources/config'));
$loader->load('services.yaml');
$container->compile();
  • 将此容器实例注入到应用程序中。或者扩展ContanerBuilder类,使其成为单例。

应用程序中使用的服务应该是公共的,因此您可以直接从容器中获取它们:

$service = $container->get(\App\Services\MyService::class);

默认情况下,您还可以公开所有服务:

services:
    _defaults:
        public: true
 类似资料:
  • 我有一些C语言的遗留程序,它们基于输入文件工作,结果进入输出文件。这两个文件都在程序参数中指定。因此,调用如下所示: 根据Artem Bilan的建议,我用下面的Spring配置文件创建了这个项目。它可以调用可执行文件!然而,我仍然存在出站通道的问题。首先,它不包含任何内容,我得到错误“不支持的消息负载类型”。其次,更重要的是,我需要用Java程序处理输出文件a.out。组织此工作流的最佳方式是什

  • 问题内容: 我正在开发一个小型Java EE Hibernate Spring应用程序,出现错误: 这是我的控制器ArticleControleur,其中包含用于恢复文章列表的功能: 这是我的articleService: 这是我的应用程序上下文: 问题答案: 该错误表明不是注册的Bean。添加其中包含将在你的应用程序上下文中自动装配的bean的软件包: 或者,如果你想将所有子包包括在com.bd

  • 我正在浏览与依赖项注入相关的Symfony 2文档,但找不到自动连线的参考。我发现一个捆绑包提供了一些这方面的功能,但它仍处于测试阶段,似乎与注释有关(如果我错了,请纠正我)。 我要寻找的是一个对象(比如服务容器),它可以通过setter注入在我的服务中注入依赖项。 例如,我将定义一个服务: 然后,我可以使用这个假设的服务容器在服务中注入依赖项,即使这个依赖项是在容器外部创建的: 是否有DI容器可

  • 大家好,我收到下一个错误,我是使用Hibernate的新手

  • 这是我的当前设置:ProjectRepo: ProjectService: ProjectRestController:

  • 现在我面临的问题是如何实现On-Prem和云应用程序之间的集成。我想了几个选择。 直接将消息从遗留的Tibco主题复制到。NET应用程序将消息发布到GCP中的pub/sub主题。我不是Tibco专家,不确定这是否得到支持。我找到了下面的链接,但不确定这是否适合我的用例。另外,客户想要离开Tibco,并且不确定数据中心上的遗留Tibco EMS是否支持下面的Tibco连接器功能。https://ww