如何将依赖项注入 Symfony 控制台命令?
我正在编写一个开源应用程序,使用一些 Symfony 组件,并使用 Symfony Console 组件与 shell 交互。
但是,我需要注入依赖项(在所有命令中使用),例如 Logger、Config 对象、Yaml 解析器。我通过扩展 Symfony\Component\Console\Command\Command
类解决了这个问题。但这使得单元测试变得更加困难并且看起来不正确。
我该如何解决这个问题?
I'm writing an open source application uses some Symfony components, and using Symfony Console component for interacting with shell.
But, i need to inject dependencies (used in all commands) something like Logger, Config object, Yaml parsers.. I solved this problem with extending Symfony\Component\Console\Command\Command
class. But this makes unit testing harder and not looks correct way.
How can i solve this ?
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(8)
自 Symfony 4.2 起,ContainerAwareCommand 已被弃用。请改用 DI。
Since Symfony 4.2 the ContainerAwareCommand is deprecated. Use the DI instead.
最好不要注入容器本身,而是将容器中的服务注入到对象中。如果您使用 Symfony2 的容器,那么您可以执行以下操作:
MyBundle/Resources/config/services (或您决定放置此文件的任何位置):
然后您的命令类应该如下所示:
我知道您说您是不使用依赖项注入容器,但为了实现@ramon 的上述答案,您必须使用它。至少这样你的命令可以被正确地进行单元测试。
It is best not to inject the container itself but to inject services from the container into your object. If you're using Symfony2's container, then you can do something like this:
MyBundle/Resources/config/services (or wherever you decide to put this file):
Then your command class should look like this:
I know you said you're not using the dependency injection container, but in order to implement the above answer from @ramon, you have to use it. At least this way your command can be properly unit tested.
从 ContainerAwareCommand 扩展您的 Command 类,并使用
$this->getContainer()->get('my_service_id');
获取服务Extends your Command class from ContainerAwareCommand and get the service with
$this->getContainer()->get('my_service_id');
您可以使用 ContainerCommandLoader 来提供 PSR-11 容器,如下所示:
ChangeMode 类可以定义如下:
注意:ChangeMode 应在容器配置中提供。
You can use ContainerCommandLoader in order to provide a PSR-11 container as follow:
ChangeMode class could be defined as follow:
NB.: ChangeMode should be provided in the Container configuration.
我说的是 symfony2.8。您无法将构造函数添加到扩展 ContainerAwareCommand 的类中,因为扩展类具有
$this->getContainer()
,它让您能够获取服务,而不是通过构造函数注入服务。您可以执行
$this->getContainer()->get('service-name');
I'm speaking for symfony2.8. You cannot add a constructor to the class that extends the ContainerAwareCommand because the extended class has a
$this->getContainer()
which got you covered in getting your services instead of injecting them via the constructor.You can do
$this->getContainer()->get('service-name');
转到 services.yaml
将其添加到文件中(我使用 2 个现有服务作为示例):
要在根项目文件夹的终端中查看所有服务类型的列表:
您将获得一长串可以使用的服务,一行的示例如下所示:
因此,如果 CSRF 令牌服务是您正在寻找的(例如),您将使用括号中的部分作为服务: (security.csrf.token_storage)
所以您的 services.yaml 将如下所示有点像this:
然后在您的命令类中使用构造函数中的服务:
Go to services.yaml
Add This to the file(I used 2 existing services as an example):
To see a list of all services type in terminal at the root project folder:
You will get a long list of services you can use, an example of one line would look like this:
So if CSRF token services is what you are looking for(for example) you will use as a service the part in the parenthesis: (security.csrf.token_storage)
So your services.yaml will look somewhat like this:
Then in your command class use the service in the constructor:
在 Symfony 3.4 中,如果 autowire 配置正确,则可以将服务注入到命令的构造函数中。
In Symfony 3.4, if autowire is configured correctly, services can be injected into the constructor of the command.
php 8.1
交响乐6.1
php 8.1
Symfony 6.1