Symfony 3/4/5 方式
由于 2018 和Symfony 3.4+ DI 功能,您可以将命令用作服务。
感谢@TravisCarden,您可以在这里找到工作演示
简而言之:
1.应用内核
<?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())]);
}
}
};
}
}
2. 服务
# config/services.yml
services:
_defaults:
autowire: true
App\:
resource: '../app'
Symfony\Component\Console\Application:
public: true
3. Bin 文件
# 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
如果你对更详细的解释感兴趣,我写了一篇文章Why You Should Combine Symfony Console and Dependency Injection。