Рабочий пример для Symfony 4.2.4 с службами с тегами и проход компилятора :
\ App \ Service \ Strategy\ FileContext:
declare(strict_types=1);
namespace App\Service\Strategy;
class FileContext
{
/**
* @var array
*/
private $strategies;
/**
* @param FileStrategyInterface $strategy
*/
public function addStrategy(FileStrategyInterface $strategy): void
{
$this->strategies[] = $strategy;
}
/**
* @param string $type
*
* @return string
*/
public function read(string $type): string
{
/** @var FileStrategyInterface $strategy */
foreach ($this->strategies as $strategy) {
if ($strategy->isReadable($type)) {
return $strategy->read();
}
}
throw new \InvalidArgumentException('File type not found');
}
}
\ App \ Service \ Strategy \ FileStrategyInterface:
declare(strict_types=1);
namespace App\Service\Strategy;
interface FileStrategyInterface
{
/**
* @param string $type
*
* @return bool
*/
public function isReadable(string $type): bool;
/**
* @return string
*/
public function read(): string;
}
\ App \ Service \ Strategy \ CsvStrategy:
declare(strict_types=1);
namespace App\Service\Strategy;
class CsvStrategy implements FileStrategyInterface
{
private const TYPE = 'csv';
/**
* {@inheritdoc}
*/
public function isReadable(string $type): bool
{
return self::TYPE === $type;
}
/**
* {@inheritdoc}
*/
public function read(): string
{
return 'Read CSV file';
}
}
\ App \ Service \ Strategy \ TxtStrategy:
class TxtStrategy implements FileStrategyInterface
{
private const TYPE = 'txt';
/**
* {@inheritdoc}
*/
public function isReadable(string $type): bool
{
return self::TYPE === $type;
}
/**
* {@inheritdoc}
*/
public function read(): string
{
return 'Read TXT file';
}
}
\ App \ DependencyInjection \ Compiler \ FileContextCompilerPass:
declare(strict_types=1);
namespace App\DependencyInjection\Compiler;
use App\Service\Strategy\FileContext;
use Symfony\Component\DependencyInjection\Compiler\CompilerPassInterface;
use Symfony\Component\DependencyInjection\ContainerBuilder;
use Symfony\Component\DependencyInjection\Reference;
class FileContextCompilerPass implements CompilerPassInterface
{
/**
* {@inheritdoc}
*/
public function process(ContainerBuilder $container)
{
$service = $container->findDefinition(FileContext::class);
$strategyServiceIds = array_keys($container->findTaggedServiceIds('strategy_file'));
foreach ($strategyServiceIds as $strategyServiceId) {
$service->addMethodCall('addStrategy', [new Reference($strategyServiceId)]);
}
}
}
\ App \ Kernel:
namespace App;
use App\DependencyInjection\Compiler\FileContextCompilerPass;
...
class Kernel extends BaseKernel
{
use MicroKernelTrait;
...
/**
* {@inheritdoc}
*/
protected function build(ContainerBuilder $container)
{
$container->addCompilerPass(new FileContextCompilerPass());
}
}
Убедитесь, что вы добавили допустимые определения служб с тэгом.
config / services.yaml:
App\Service\Strategy\TxtStrategy:
tags:
- { name: strategy_file }
App\Service\Strategy\CsvStrategy:
tags:
- { name: strategy_file }
Команда для тестирования. \ App \ Command \ StrategyCommand:
declare(strict_types=1);
namespace App\Command;
use App\Service\Strategy\FileContext;
use Symfony\Component\Console\Command\Command;
use Symfony\Component\Console\Input\InputInterface;
use Symfony\Component\Console\Input\InputOption;
use Symfony\Component\Console\Output\OutputInterface;
class StrategyCommand extends Command
{
/**
* {@inheritdoc}
*/
protected static $defaultName = 'strategy:run';
/**
* @var FileContext
*/
private $fileContext;
/**
* @param FileContext $fileContext
*/
public function __construct(FileContext $fileContext)
{
$this->fileContext = $fileContext;
parent::__construct();
}
/**
* {@inheritdoc}
*/
protected function configure()
{
$this
->setDescription('Run strategy example')
->addOption('file', null, InputOption::VALUE_REQUIRED);
}
/**
* {@inheritdoc}
*/
protected function execute(InputInterface $input, OutputInterface $output)
{
if (!$file = trim($input->getOption('file'))) {
return;
}
echo $this->fileContext->read($file);
}
}
Результат:
$ bin/console strategy:run --file=txt
Read TXT file%
$ bin/console strategy:run --file=csv
Read CSV file%