Symfony 4 - 服务被删除或内联,虽然它是公开的

Ben*_*Ben 10 dependency-injection symfony symfony-flex symfony4

我正在尝试使用新的目录结构和所有内容将SF 3.3应用程序迁移到SF 4.

我在这个例外上苦苦挣扎:

编译容器时,"simplethings_entityaudit.reader"服务或别名已被删除或内联.您应该将其公开,或者直接停止使用容器并改为使用依赖注入.

(此服务来自/ vendor中的外部包).

然而,当我bin/console debug:container simplethings_entityaudit.reader看到服务存在并且是公开的时候:

Information for Service "simplethings_entityaudit.reader"
=========================================================

 ----------------- -------------------------------------- 
  Option            Value                                 
 ----------------- -------------------------------------- 
  Service ID        simplethings_entityaudit.reader       
  Class             SimpleThings\EntityAudit\AuditReader  
  Tags              -                                     
  Public            yes                                   
  Synthetic         no                                    
  Lazy              no                                    
  Shared            yes                                   
  Abstract          no                                    
  Autowired         no                                    
  Autoconfigured    no                                    
  Factory Service   simplethings_entityaudit.manager      
  Factory Method    createAuditReader                     
 ----------------- -------------------------------------- 

此服务目前在我自己的一个中调用$this->container->get('simplethings_entityaudit.reader').

我也尝试注入SimpleThings\EntityAudit\AuditReader我的服务构造函数,但这是我得到的:

方法"__construct()"的参数"$ auditReader"引用类"SimpleThings\EntityAudit\AuditReader"但不存在此类服务.它无法自动注册,因为它来自不同的根命名空间.

当我将services.yaml它添加到我的工作中时,我不应该这样做:

SimpleThings\EntityAudit\AuditReader:
    alias: simplethings_entityaudit.reader
Run Code Online (Sandbox Code Playgroud)

有任何想法吗?

Hen*_*ilz 10

就我而言,错误出现在单元测试中。

我有一个服务,无法在测试(Symfony 4.2)中加载,而我项目中的所有其他服务都运行良好。

我已经清除了缓存,但没有帮助。然后我创建了一个带有路由的简单控制器,并将服务作为方法参数注入。之后,该服务也适用于我的测试。

结论:如果你有一个单元测试,想要测试你的服务,你还必须提供一个控制器,服务注入的地方,否则在测试服务容器中是不可用的。显式的服务配置也可能有所帮助。

  • 这至少部分是不正确的。添加控制器可能只是将服务标记为已使用,因此在容器转储期间不会对其进行修剪。 (3认同)

Sol*_*ber 10

在我们的例子中,我们做了一个services_test.yml与设置.env.testAPP_ENVtest

然后在其中services_test.yml我们放置

services:
    _defaults:
        public: true
Run Code Online (Sandbox Code Playgroud)

所以默认情况下所有服务都是公共的

不要忘记获取你的资源.env.env.test我经常必须这样做,我们重新启动我的虚拟机


Edi*_*rić 8

在 Symfony 4.0 中,任何未指定其可见性的服务都是私有的,https://github.com/symfony/symfony/pull/24238

据我所知,您提到的服务没有指定可见性:https : //github.com/simplethings/EntityAuditBundle/blob/1.0/src/SimpleThings/EntityAudit/Resources/config/auditable.xml#L23-L26,所以这可能是您例外的原因。

如果simplethings_entityaudit.reader服务无法自动装配(这可能是因为它使用了工厂服务),您可以通过使用以下@simplethings_entityaudit.reader符号引用它来将其注入到您自己的服务中:https : //symfony.com/doc/current/service_container.html #services-manually-wire-args,像这样:

services:
    My\Service:
        arguments:
            $auditReader: @simplethings_entityaudit.reader
Run Code Online (Sandbox Code Playgroud)

  • 是的,正如您所建议的和您发布的文档,其中一个选项是使用“public: true”设置服务可见性 (3认同)
  • 这实际上是在最新的 Symfony 4.0.x 版本中修复的错误。 (2认同)

Cod*_*rit 5

我单位也有同样的问题KernelTestCase

当您尝试使用未在应用程序中任何地方引用的容器加载服务时,就会出现问题。要修复它,只需将该服务包含在控制器中或始终在应用程序中注册的另一个服务中,或者在services.yaml.

// Doesnt work in test case when not registered somewhere else
static::getContainer()->get(MyService::class);

Run Code Online (Sandbox Code Playgroud)

但是如果我们在某个地方引用它,我们就可以在测试中使用容器来获取它:

class MyController {

  public function __construct(protected MyService $myService) {}

}


class AnotherTestCase extends KernelTestCase {

  public function setUp() {
    // Now works because service is used in controller and therefore present in compiled container.
    $myService = static::getContainer()->get(MyService::class);
  }
}

Run Code Online (Sandbox Code Playgroud)