静态值配twig.yaml,动态值须服务注入;静态如site_name配globals块,动态需实现GlobalsExtensionInterface并打twig.extension标签,禁用DB/API调用。

静态值直接写 twig.yaml,动态值必须走服务注入——别在配置文件里调数据库或调 API,那会让每个页面都变慢。
静态全局变量:直接配 twig.yaml
适合网站名、开关标志、CDN 域名这类不变的值。Symfony 5.4+ 默认路径是 config/packages/twig.yaml,在 twig: 下加 globals: 块即可:
twig:
globals:
site_name: '%env(APP_NAME)%'
ga_id: '%env(GA_ID)%'
is_production: '%kernel.environment%' == 'prod'
注意三点:
-
%env(...)%和%kernel.environment%这类参数引用要确保已在容器中定义,否则会报The environment variable "APP_NAME" does not exist - 布尔值写法要小心:
true/false是 YAML 布尔字面量,但'true'(带引号)会被当字符串,模板里用if is_production就会恒为真 - 值不能是对象、资源或闭包——YAML 解析器不认,会直接抛
InvalidTypeException
动态全局变量:必须实现 GlobalsExtensionInterface
比如要全局暴露 {{ stats.users_count }} 或 {{ theme.colors.primary }},就得靠服务。核心是两步:写个类实现接口,再注册为服务。
例如创建 src/Twig/GlobalsExtension.php:
namespace App\Twig;
use Twig\Extension\GlobalsExtensionInterface;
use Symfony\Contracts\Service\ServiceSubscriberInterface;
class GlobalsExtension implements GlobalsExtensionInterface, ServiceSubscriberInterface
{
private $statsService;
public function __construct(StatsService $statsService)
{
$this->statsService = $statsService;
}
public static function getSubscribedServices(): array
{
return ['App\Service\StatsService'];
}
public function getGlobals(): array
{
// 注意:这里只做轻量计算,重逻辑放 service 里
return [
'stats' => [
'users_count' => $this->statsService->getUserCount(),
'posts_count' => $this->statsService->getPostCount(),
],
'theme' => $this->statsService->getThemeConfig(),
];
}
}
然后在 config/services.yaml 中声明服务并打上标签:
App\Twig\GlobalsExtension:
tags: [{ name: 'twig.extension' }]
关键点:
- 不要在
getGlobals()里做 DB 查询或 HTTP 请求——它会在每次模板渲染时执行;把耗时操作封装进 service,这里只调方法 - 返回数组必须是纯 PHP 类型(int/string/array),不能含对象实例(除非该对象实现了
__toString或被 Twig 自动转换) - 若依赖其他服务,用
ServiceSubscriberInterface而非构造函数注入,避免循环依赖风险
调试全局变量是否生效
最简单的方式是打开 dev 环境的 dump 功能,在任意模板里加:
{% if app.debug %}{{ dump(_context|keys) }}{% endif %}
看输出里有没有你配的键名(如 site_name 或 stats)。如果没出现,常见原因有:
-
twig.yaml的缩进错位——YAML 对空格敏感,globals:必须和debug:同级 - 服务没打
twig.extension标签,或者类没实现GlobalsExtensionInterface - 缓存没清:运行
php bin/console cache:clear,别只删var/cache/dev目录 - 变量名冲突:比如你定义了
app,会覆盖 Twig 内置的app全局对象,导致app.user失效
真正难的不是配出来,而是判断该不该配——一个只在首页侧边栏用一次的计数器,不如在对应 Controller 里传;只有跨十几个模板、复用率高、且计算开销可控的数据,才值得进全局。


















