Php 如果没有Symfony框架捆绑包,如何将Symfony控制台与依赖项注入一起使用?

Php 如果没有Symfony框架捆绑包,如何将Symfony控制台与依赖项注入一起使用?,php,symfony,dependency-injection,symfony-console,Php,Symfony,Dependency Injection,Symfony Console,我有一个命令行应用程序,目前为止它使用Symfony依赖项注入组件。现在我发现我想添加命令行选项并改进输出的格式,而Symfony控制台组件似乎是一个很好的选择 但是,我不知道如何让Symfony控制台命令类接收容器对象 我发现的文档使用了ContainerWareCommand类,但这是来自FrameworkBundle的,这似乎给纯CLI应用程序增加了大量开销,因为它需要更多的bundle,如路由、http、配置、缓存等,这些都与我无关 (顺便说一句,现有的SO问题也假设框架包。) 我在这里

我有一个命令行应用程序,目前为止它使用Symfony依赖项注入组件。现在我发现我想添加命令行选项并改进输出的格式,而Symfony控制台组件似乎是一个很好的选择

但是,我不知道如何让Symfony控制台命令类接收容器对象

我发现的文档使用了ContainerWareCommand类,但这是来自FrameworkBundle的,这似乎给纯CLI应用程序增加了大量开销,因为它需要更多的bundle,如路由、http、配置、缓存等,这些都与我无关

(顺便说一句,现有的SO问题也假设框架包。)


我在这里用一个基本命令创建了一个测试存储库,说明了这个问题:

是的,不需要整个框架。在您的情况下,首先需要创建一种输入脚本。诸如此类:

<?php

require 'just/set/your/own/path/to/vendor/autoload.php';

use Symfony\Component\Console\Application;
use Symfony\Component\DependencyInjection\ContainerBuilder;

$container = new ContainerBuilder();
$container
    ->register('your_console_command', 'Acme\Command\YourConsoleCommand')
    ->addMethodCall('setContainer', [new Reference('service_container')]);
$container->compile();

$application = new Application();
$application->add($container->get('your_console_command'));
$application->run();
Symfony 3/4/5路
从2018年到现在,您可以将命令用作服务

多亏了@TravisCarden,你可以

简言之:

1.应用程序内核 3.Bin文件 运行它

如果你对更详细的解释感兴趣,我写了一篇帖子。

你链接的第二个答案呢?这看起来是一个很好的解决方案!Symfony 4是否需要更改?我试过了,但出现了一个异常,说它找不到
应用程序的服务定义。谢谢!不,您只需要在配置中注册
Symfony\Component\Console\Application
。我已经更新了答案谢谢你,@tomáš-votruba,但我仍然想得到同样的错误。我根据您的答案创建了一个概念证明,并在上为其创建了一个GitHub回购协议。你想看看有什么问题吗?也许我们可以验证一个完整的解决方案并相应地更新答案。谢谢,@tomáš-votruba。我已经更新了回购协议,以反映您的最新编辑。这个改变是有道理的,但我还是犯了一个致命的错误。我想知道我们在翻译方面是否失去了一些东西。您介意向我的repo发送一个pull请求吗?检查一下:如果您同意的话,我还为答案添加了指向存储库演示的链接。
<?php

# app/Kernel.php

namespace App;

use Symfony\Component\Config\Loader\LoaderInterface;
use Symfony\Component\Console\Application;
use Symfony\Component\Console\Command\Command;
use Symfony\Component\DependencyInjection\Compiler\CompilerPassInterface;
use Symfony\Component\DependencyInjection\Reference;
use Symfony\Component\HttpKernel\Kernel;
use Symfony\Component\DependencyInjection\ContainerBuilder;

final class AppKernel extends Kernel
{
    public function registerBundles(): array
    {
        return [];
    }

    public function registerContainerConfiguration(LoaderInterface $loader): void
    {
        $loader->load(__DIR__.'/../config/services.yml');
    }

    protected function build(ContainerBuilder $containerBuilder): void
    {
        $containerBuilder->addCompilerPass($this->createCollectingCompilerPass());
    }

    private function createCollectingCompilerPass(): CompilerPassInterface
    {
        return new class implements CompilerPassInterface
        {
            public function process(ContainerBuilder $containerBuilder)
            {
                $applicationDefinition = $containerBuilder->findDefinition(Application::class);

                foreach ($containerBuilder->getDefinitions() as $definition) {
                    if (! is_a($definition->getClass(), Command::class, true)) {
                        continue;
                    }

                    $applicationDefinition->addMethodCall('add', [new Reference($definition->getClass())]);
                }
            }
        };
    }
}
# config/services.yml

services:
    _defaults:
        autowire: true

    App\:
        resource: '../app'

    Symfony\Component\Console\Application:
        public: true
# index.php

require_once __DIR__ . '/vendor/autoload.php';

use Symfony\Component\Console\Application;

$kernel = new AppKernel;
$kernel->boot();

$container = $kernel->getContainer();
$application = $container->get(Application::class)
$application->run();
php index.php