【问题标题】:RenderView in Symfony Command usageSymfony 命令中的 RenderView 使用
【发布时间】:2015-09-15 20:15:54
【问题描述】:

如何在 symfony 命令中使用 $this->renderView(不在控制器中)?我对“renderView”函数有新的了解,但我必须设置什么才能在命令中使用它?

提前谢谢你的问候

【问题讨论】:

    标签: symfony render


    【解决方案1】:

    你的命令类必须扩展 ContainerAwareCommand abstract class 然后你可以这样做:

    $this->getContainer()->get('templating')->render($view, $parameters);
    

    当涉及到扩展 ContainerAwareCommand 的命令时,获取容器的正确方法是通过 getContainer() 与控制器快捷方式不同。

    【讨论】:

    • 谢谢,这就是它完美的工作方式。嗯,谢谢你的回复!!
    • 关于命令的另一个问题:如何在命令中访问 security.content? $user = $this->get('security.context')->getToken()->getUser();这行不通,所以我又卡住了:(
    • 可能是因为$this->get('security.context')->getToken() === null
    • 嗯,这可能是因为我通过控制台调用它。因此没有人必须登录。嗯,我的错。抱歉,谢谢提示!
    • 我试过了,但我收到错误消息“您请求了一个不存在的服务“模板化”。”
    【解决方案2】:

    在 Symfony 4 中,我无法让 $this->getContainer()->get('templating')->render($view, $parameters); 工作。

    我为 Symfony\Bundle\FrameworkBundle\Command\ContainerAwareCommand 和扩展的 ContainerAwareCommand class EmailCommand extends ContainerAwareCommand 设置命名空间使用

    我抛出异常

    [Symfony\Component\DependencyInjection\Exception\ServiceNotFoundException]
          You have requested a non-existent service "templating".
    

    对于 Symfony 4,这是我想出的解决方案。

    首先我安装了 Twig。

    composer require twig
    

    然后创建了我自己的 twig 服务。

    <?php
    
    # src/Service/Twig.php
    
    namespace App\Service;
    
    use Symfony\Component\HttpKernel\KernelInterface;
    
    class Twig extends \Twig_Environment {
    
        public function __construct(KernelInterface $kernel) {
            $loader = new \Twig_Loader_Filesystem($kernel->getProjectDir());
    
            parent::__construct($loader);
        }
    }
    

    现在我的电子邮件命令如下所示。

    <?php
    
    # src/Command/EmailCommand.php
    
    namespace App\Command;
    
    use Symfony\Component\Console\Command\Command,
        Symfony\Component\Console\Input\InputInterface,
        Symfony\Component\Console\Output\OutputInterface,
        App\Service\Twig;
    
    class EmailCommand extends Command {
    
        protected static $defaultName = 'mybot:email';
    
        private $mailer,
                $twig;
    
        public function __construct(\Swift_Mailer $mailer, Twig $twig) {
            $this->mailer = $mailer;
            $this->twig = $twig;
    
            parent::__construct();
        }
    
        protected function configure() {
            $this->setDescription('Email bot.');
        }
    
        protected function execute(InputInterface $input, OutputInterface $output) {
    
            $template = $this->twig->load('templates/email.html.twig');
    
            $message = (new \Swift_Message('Hello Email'))
                ->setFrom('emailbot@domain.com')
                ->setTo('someone@somewhere.com')
                ->setBody(
                    $template->render(['name' => 'Fabien']),
                    'text/html'
                );
    
            $this->mailer->send($message);
        }
    }
    

    【讨论】:

    • 因为服务默认是私有的,这意味着在容器编译过程中被移除,因此之后不可用。您可以通过运行debug:container templating 命令来验证这一点。您可以改为注入 EngineInterface,最终会自动连接 Twig。
    • @Mike 有没有办法让核心服务(默认情况下对控制台不可用)可用?编辑(刚刚看到你的解决方案)
    • 您的意思是公开私人服务?当然,只需 declare them public 在您的 services.yml 之类的。
    • @Mike 谢谢你的时间。我很难将模板声明为公开。我应该在 services.yml 中公开的模板名称是什么?
    • 你试过EngineInterface吗?如果不将其声明为templating 服务的别名并声明为public。然而,命令即服务是一种更好的方法。该类更容易测试。
    【解决方案3】:

    还有一个:依赖依赖注入,即注入ContainerInterface

    namespace AppBundle\Command;
    
    use Symfony\Component\Console\Command\Command;
    use Symfony\Component\Console\Input\InputInterface;
    use Symfony\Component\Console\Output\OutputInterface;
    use Psr\Container\ContainerInterface;
    
    class SampleCommand extends Command
    {
        public function __construct(ContainerInterface $container)
        {
            $this->templating = $container->get('templating');
            parent::__construct();
        }
    
        protected function configure()
        {
            $this->setName('app:my-command')
                 ->setDescription('Do my command using render');
        }
    
        protected function execute(InputInterface $input, OutputInterface $output)
        {
            $data = retrieveSomeData();
            $csv = $this->templating->render('path/to/sample.csv.twig',
                                             array('data' => $data));
            $output->write($csv);
        }
    
        private $templating;
    }
    

    这依赖于 Symfony 注入容器,而容器又用于检索 templatingtwig 或任何您需要的自定义命令。

    【讨论】:

    • 使用 templating 服务自 Symfony 4.2 起已被弃用
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2017-01-11
    • 1970-01-01
    • 2017-09-05
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多