简体   繁体   English

Symfony控制台ContainerAwareCommand $ this-> getContainer()产生致命错误

[英]Symfony Console ContainerAwareCommand $this->getContainer() produces Fatal error

TL;DR TL; DR

I'm creating console Garbage collector, which should be able to get services from container. 我正在创建控制台垃圾收集器,它应该能够从容器中获取服务。 It's basic, almost straight from the manual: 它是基本的,几乎与手册完全一样:

<?php
namespace SomeBundle\Console\Command;

use Symfony\Bundle\FrameworkBundle\Command\ContainerAwareCommand,
    Symfony\Component\Console\Input\InputArgument,
    Symfony\Component\Console\Input\InputInterface,
    Symfony\Component\Console\Input\InputOption,
    Symfony\Component\Console\Output\OutputInterface;

class GarbageCollector extends ContainerAwareCommand
{
    protected function configure()
    {
        $this
            ->setName('garbage:collect')
            ->setDescription('Collect garbage')
            ->addArgument(
                'task',
                InputArgument::REQUIRED,
                'What task to execute?'
            )
        ;
    }

    protected function execute(InputInterface $input, OutputInterface $output)
    {
        $task = $input->getArgument('task');

        //...

        $_container = $this->getContainer();
    }
}

Then I'm trying to call it from console via application.php : 然后我试图通过application.php从控制台调用它:

#!/usr/bin/env php
<?php
// application.php

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

use SomeBundle\Console\Command\GarbageCollector;
use Symfony\Bundle\FrameworkBundle\Console\Application;

$application = new Application();
$application->add(new GarbageCollector);
$application->run();

Which produces fatal error: 产生致命错误:

Argument 1 passed to Symfony\\Bundle\\FrameworkBundle\\Console\\Application::__construct() must implement interface Symfony\\Component\\HttpKernel\\Kernel Interface, none given 传递给Symfony \\ Bundle \\ FrameworkBundle \\ Console \\ Application :: __ construct()的参数1必须实现接口Symfony \\ Component \\ HttpKernel \\ Kernel接口,未给出

Manual says that only thing I need to do is to extend my class with ContainerAwareCommand , but something missing. 手册说,我唯一需要做的就是用ContainerAwareCommand扩展我的类,但是缺少一些东西。 I've wrote some crap code to pass Kernel to the Application() : 我写了一些废话代码,将Kernel传递给Application()

#!/usr/bin/env php
<?php
// application.php

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

use SomeBundle\Console\Command\GarbageCollector;
use Symfony\Bundle\FrameworkBundle\Console\Application;
use Symfony\Component\Console\Input\ArgvInput;

$input = new ArgvInput();
$env = $input->getParameterOption(array('--env', '-e'), getenv('SYMFONY_ENV') ?: 'dev');
$debug = getenv('SYMFONY_DEBUG') !== '0' && !$input->hasParameterOption(array('--no-debug', '')) && $env !== 'prod';

$kernel = new AppKernel($env, $debug);
$application = new Application($kernel);
$application->add(new GarbageCollector);
$application->run();

And it works, but feels disgusting. 它有效,但令人恶心。

What do I need to make ContainerAwareCommand implementation of console app? 我需要什么来使ContainerAwareCommand实现控制台应用程序? Thanks in advance. 提前致谢。

Symfony2 provides via its console runner the ability to call your custom commands and it will handle the injection of the service container. Symfony2通过其控制台运行程序提供了调用自定义命令的功能,它将处理服务容器的注入。 All you need to do is create your command in a registered bundle and it will automatically become available to you. 您需要做的就是在已注册的捆绑软件中创建命令,该命令将自动变为可用状态。 You are initializing your command outside of the framework that is why the container is not available to you unless you manually inject it. 您正在框架外部初始化命令,这就是除非您手动注入容器,否则容器不可用的原因。

You can reference the cookbook here: 您可以在此处参考食谱:

http://symfony.com/doc/current/cookbook/console/console_command.html http://symfony.com/doc/current/cookbook/console/console_command.html

You can get a list of all the commands available by running: 您可以通过运行以下命令获取所有可用命令的列表:

php app/console 

On a side note, why are you creating a garbage collector in/for PHP? 附带说明一下,为什么要在PHP中/为PHP创建垃圾收集器? Just curious because to my understanding memory is freed for you after script execution has ended. 只是好奇,因为据我所知,脚本执行结束后会为您释放内存。

As by version 4.1 you can inject the container service at the constructor. 与4.1版一样,您可以在构造函数中注入容器服务。

namespace App\Commands;

use Symfony\Component\Console\Command\Command;
use Symfony\Component\Console\Input\InputInterface;
use Symfony\Component\Console\Output\OutputInterface;
use Symfony\Component\DependencyInjection\ContainerInterface;

class MyCommand extends Command {
    protected $container;

    public function __construct(ContainerInterface $container) {
        $this->container = $container;
        parent::__construct();
    }


    protected function configure() {
        // ...
    }

    protected function execute(InputInterface $input, OutputInterface $output) {
        // You must make Some\Service\Class public.
        // Documentation at https://symfony.com/doc/current/service_container.html#public-versus-private-services
        $some_service = $this->container->get('Some\Service\Class');
    }
}

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM