Symfony 4.2+:替换 ContainerAwareCommand 的 getContainer->get()

k00*_*0ni 1 dependency-injection symfony symfony-4.2

我的目标

在 Plesk 中,我想经常使用 PHP 7.2 运行 PHP 脚本。它必须是 PHP 脚本,而不是控制台命令(有关更多详细信息,请参阅“我的环境”)。我当前基于 Symfony 4.2 的实现工作正常,但它被标记为deprecated

如前所述这里,将ContainerAwareCommand被标记deprecated在Symfony的4.2。不幸的是,关于如何在未来解决此问题的参考文章不包含有关它的信息。

我的环境

我的共享虚拟主机 (Plesk) 使用 PHP 7.0 运行,但允许脚本使用 PHP 7.2 运行。以后只有在它直接运行 PHP 脚本而不是作为控制台命令时才有可能。我需要 PHP 7.2。

我知道Symfony 中的注入类型。根据我目前的知识,这个问题只能通过使用该getContainer方法或手动提供所有服务(例如通过构造函数)来解决,这会导致代码混乱。

当前解决方案

文件:cron1.php

<?php

// namespaces, Dotenv and gathering $env and $debug
// ... 

$kernel = new Kernel($env, $debug);

$app = new Application($kernel);
$app->add(new FillCronjobQueueCommand());
$app->setDefaultCommand('fill_cronjob_queue');
$app->run();
Run Code Online (Sandbox Code Playgroud)

文件:FillCronjobQueueCommand.php

<?php 

// ...

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

class FillCronjobQueueCommand extends ContainerAwareCommand
{
    protected function configure()
    {
        $this->setName('fill_cronjob_queue');
    }

    protected function execute(InputInterface $input, OutputInterface $output)
    {
        // using "$this->getContainer()" is deprecated since Symfony 4.2 
        $manager = $this->getContainer()->get('doctrine')->getManager();

        $cron_queue_repo = $manager->getRepository(CronjobQueue::class);

        $cronjobs = $manager->getRepository(Cronjob::class)->findAll();

        $logger = $this->getContainer()->get('logger');

        // ...
    }
}

Run Code Online (Sandbox Code Playgroud)

小智 7

暂时回答

就我而言,只要没有另外说明,复制 ContainerAwareCommand 类似乎是最好的方法(感谢“Cerad”)。这使我可以保留当前功能并摆脱不推荐使用的警告。对我来说,它也是临时解决方案(直到 Hoster 升级到 PHP 7.2),因此对 Symfony 未来的主要升级没有影响。

不过,我推荐下面的答案,并将在未来实施。


推荐答案

根据 symfony 网站Deprecated ContainerAwareCommand上的这篇博客文章

另一种方法是从 Command 类扩展命令并在命令构造函数中使用适当的服务注入

所以正确的方法是:

<?php 

// ...

use Symfony\Component\Console\Command\Command
use Symfony\Component\Console\Input\InputInterface;
use Symfony\Component\Console\Output\OutputInterface;
use Doctrine\ORM\EntityManagerInterface;
use PSR\Log\LoggerInterface;

class FillCronjobQueueCommand extends Command
{
    public function __construct(EntityManagerInterface $manager, LoggerInterface $logger)
    {
        $this->manager = $manager;
        $this->logger = $logger;
    }

    protected function configure()
    {
        $this->setName('fill_cronjob_queue');
    }

    protected function execute(InputInterface $input, OutputInterface $output)
    {
        $cron_queue_repo = $this->manager->getRepository(CronjobQueue::class);

        $cronjobs = $this->manager->getRepository(Cronjob::class)->findAll();

        // ...
    }
}
Run Code Online (Sandbox Code Playgroud)