Symfony Console ContainerAwareCommand $ this-> gt; getContainer () выдает фатальную ошибку

TL; DR

Я создаю консольный сборщик мусора, который должен иметь возможность получать сервисы из контейнера.
Это просто, почти прямо из руководства:

<?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();
}
}

Тогда я пытаюсь позвонить с консоли через 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();

Что приводит к фатальной ошибке:

Аргумент 1 передан
Symfony \ Bundle \ FrameworkBundle \ Console \ Application :: __ construct () должен
реализовать интерфейс Symfony \ Component \ HttpKernel \ Kernel Interface,
никто не дал

Руководство говорит, что единственное, что мне нужно сделать, это расширить свой класс ContainerAwareCommand, но чего-то не хватает. Я написал немного кода дерьма, чтобы передать 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();

И это работает, но чувствует себя отвратительно.

Что мне нужно сделать ContainerAwareCommand реализация консольного приложения? Заранее спасибо.

2

Решение

Symfony2 предоставляет через своего консольного бегуна возможность вызывать ваши пользовательские команды, и он будет обрабатывать внедрение сервисного контейнера. Все, что вам нужно сделать, это создать свою команду в зарегистрированном пакете, и она автоматически станет вам доступна. Вы инициализируете свою команду вне фреймворка, поэтому контейнер недоступен вам, если вы не добавили его вручную.

Вы можете сослаться на кулинарную книгу здесь:

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

Вы можете получить список всех доступных команд, выполнив:

php app/console

Кстати, почему вы создаете сборщик мусора в / для PHP? Просто любопытно, потому что, насколько я понимаю, память освобождается для вас после завершения выполнения скрипта.

4

Другие решения

Как и в версии 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');
}
}
1