Symfony 3.4命令中使用Swift Mailer报错,求正确实现方法
在Symfony 3.4命令中正确使用Swift Mailer的解决方案
你遇到的错误核心原因很明确:容器实例本身并没有renderView方法——这个方法属于templating服务(Symfony\Bundle\FrameworkBundle\Templating\EngineInterface),并不是容器对象的内置方法。下面给你两种可行的解决方式:
方式一:直接获取templating服务(快速修复)
只需要修改代码中渲染视图的部分,先从容器中拿到templating服务,再调用它的renderView方法即可:
namespace AppBundle\Command; use Symfony\Component\Console\Command\Command; use Symfony\Component\Console\Input\InputInterface; use Symfony\Component\Console\Output\OutputInterface; use Symfony\Bundle\FrameworkBundle\Command\ContainerAwareCommand; use Swift_Message; class NotificationCommand extends ContainerAwareCommand { protected function configure() { $this->setName('app:notif'); } public function execute(InputInterface $input, OutputInterface $output) { $message = Swift_Message::newInstance() ->setFrom([ 'from@example.com' => 'Example' ]) ->setTo('to@example.com') ->setSubject('Subject') ->setBody( // 先获取templating服务,再调用renderView方法 $this->getContainer()->get('templating')->renderView( 'emails/notify.html.twig', [ 'foo' => 'bar' ] ), 'text/html' ); $this->getContainer()->get('mailer')->send($message); $output->writeln('通知邮件已成功发送!'); } }
方式二:使用构造函数注入(推荐,符合Symfony最佳实践)
Symfony 3.4开始更推荐用构造函数注入替代ContainerAwareCommand,这种方式更清晰,也方便后续测试。我们直接在构造函数中注入需要的templating和mailer服务:
namespace AppBundle\Command; use Symfony\Component\Console\Command\Command; use Symfony\Component\Console\Input\InputInterface; use Symfony\Component\Console\Output\OutputInterface; use Symfony\Bundle\FrameworkBundle\Templating\EngineInterface; use Swift_Mailer; use Swift_Message; class NotificationCommand extends Command { private $templating; private $mailer; public function __construct(EngineInterface $templating, Swift_Mailer $mailer) { $this->templating = $templating; $this->mailer = $mailer; parent::__construct(); } protected function configure() { $this->setName('app:notif'); } public function execute(InputInterface $input, OutputInterface $output) { $message = Swift_Message::newInstance() ->setFrom([ 'from@example.com' => 'Example' ]) ->setTo('to@example.com') ->setSubject('Subject') ->setBody( $this->templating->renderView( 'emails/notify.html.twig', [ 'foo' => 'bar' ] ), 'text/html' ); $this->mailer->send($message); $output->writeln('通知邮件已成功发送!'); } }
如果你的命令没有被框架自动注册,需要在app/config/services.yml中手动配置服务:
services: AppBundle\Command\NotificationCommand: arguments: - '@templating' - '@mailer' tags: - { name: console.command }
错误原因复盘
你原来的代码尝试调用$this->getContainer()->renderView(),但ContainerV5drzta\appDevDebugProjectContainer这个容器类并没有renderView方法——这个方法是templating服务的核心方法,必须先通过容器获取该服务实例,才能调用对应的方法。
内容的提问来源于stack exchange,提问作者vakunenko
相关产品推荐
相关产品推荐

