Symfony 3静态函数用renderView失败,依赖注入后仍报错
咱们先拆解你遇到的核心问题:一开始静态函数里用self::renderView无效,后来改成依赖注入templating却还是报错,本质是对Symfony的服务机制和依赖注入逻辑理解有偏差,下面一步步帮你理清并修复。
一、为什么最初的self::renderView行不通?
renderView是Symfony框架里控制器基类或者templating/twig服务**提供的方法,并不是你自己写的Mails类的静态方法。你直接用self::`调用,相当于在自己的类里找这个静态方法,自然会报错。
而且静态函数本身不依赖类实例,没办法直接访问依赖注入的服务(比如渲染模板的Twig),所以从设计角度来说,把邮件发送写成静态函数并不是最优解——依赖注入才是处理这类需要调用外部服务场景的正确方式,你后来改成实例方法的方向是对的,但配置上出了问题。
二、当前依赖注入配置的错误点及修复方案
你的代码里有几个关键错误,逐个修正:
1. 控制器手动实例化Twig_Environment是错的
Twig_Environment不能直接new,它需要模板加载器、缓存配置等一系列参数,Symfony已经在容器里帮你配置好了完整的twig服务(旧版本可能是templating),你完全不需要自己手动创建实例。
2. 修正Services.yml的配置
你的服务配置格式不对,正确的依赖注入配置应该是这样:
# Services.yml services: Site\PagesBundle\Utils\Mails: arguments: ['@twig'] # Symfony 3及以后推荐用@twig,旧版本可以用@templating
3. 调整Mails类的代码
不仅要正确使用注入的Twig服务,SwiftMailer也建议通过依赖注入获取,不要手动实例化:
// Mails.php namespace Site\PagesBundle\Utils; use Twig\Environment; use Swift_Mailer; use Swift_Message; class Mails { private $twig; private $mailer; // 注入Twig和SwiftMailer服务 public function __construct(Environment $twig, Swift_Mailer $mailer) { $this->twig = $twig; $this->mailer = $mailer; } public function sendMail($user,$raisonMail) { // 直接用注入的mailer,不用自己new $message = Swift_Message::newInstance() ->setFrom(['****' => '***']) ->setTo($user->getEmail()) ->setCharset('utf-8') ->setContentType('text/html'); switch($raisonMail) { case 'formulaireInscription': $message->setSubject("Création de votre compte ATELECH prise en compte") ->setBody($this->twig->render("@Pages/swiftmail/CreationCompte/DemandeCreationCompte.html.twig",[ 'prenom' => $user->getPrenom(), 'nom' => $user->getNom(), ])); break; // 其他邮件类型的case... } // 别忘了执行发送操作 $this->mailer->send($message); } }
4. 控制器中正确获取Mails服务
在控制器里不要手动new Mails,通过Symfony的容器获取服务即可(Symfony 3.3+支持自动注入,更方便):
// DefaultController.php namespace Site\PagesBundle\Controller; use Symfony\Bundle\FrameworkBundle\Controller\AbstractController; use Site\PagesBundle\Utils\Mails; // 引入你的User类 use ...; class DefaultController extends AbstractController { public function someAction(User $user) { // 方法1:通过容器获取服务 $mailerService = $this->get(Mails::class); // 方法2:更推荐的自动注入(Symfony 3.3+),直接在构造函数注入 // public function __construct(private Mails $mailerService) {} $mailerService->sendMail($user,'formulaireInscription'); // ...其他业务逻辑 } }
三、额外提示:如果非要用静态函数怎么办?
虽然非常不推荐(不利于测试和维护,属于反模式),但如果确实需要保留静态方法,可以通过Symfony全局容器获取Twig服务:
// 不推荐的静态写法,仅作参考 public static function sendStaticMail($user) { $container = \Symfony\Component\DependencyInjection\ContainerInterface::getContainer(); $twig = $container->get('twig'); $body = $twig->render('你的模板路径', ['变量' => '值']); // 后续邮件发送逻辑 }
还是强烈建议用依赖注入的方式,这是Symfony的最佳实践。
内容的提问来源于stack exchange,提问作者eronn

