如何为Slim4+Twig(含DI容器)的所有视图添加通用模型?
嘿,我刚好对Slim4+Twig这套组合很熟,给你几个靠谱的方案来给所有视图加通用模型,比如用户对象、全局配置这些:
方案1:直接在Twig实例中注册全局变量
这是最直接的方式,适合那些不依赖请求上下文的静态全局数据(比如通用配置项)。你可以直接修改容器里Twig的初始化代码,在返回Twig实例前,用addGlobal方法把需要的变量绑定进去:
Twig::class => function (ContainerInterface $container) { $config = $container->get(Configuration::class); $twigSettings = $config->getArray('twig'); $twig = Twig::create($twigSettings['path'], $twigSettings['settings']); // 添加全局通用变量 // 1. 通用配置 $twig->addGlobal('app_config', $config->getArray('app')); // 2. 如果你的User对象是容器里可获取的(比如已登录用户) $twig->addGlobal('current_user', $container->get(User::class)); return $twig; },
这样所有Twig模板里就能直接用{{ app_config.site_name }}或者{{ current_user.name }}这类变量了。
方案2:通过中间件注入请求相关的全局变量
如果你的通用模型是和当前请求绑定的(比如从Session里取的登录用户、请求相关的参数),用中间件会更灵活。你可以自定义一个中间件来处理:
首先创建中间件类:
use Psr\Http\Message\ResponseInterface as Response; use Psr\Http\Message\ServerRequestInterface as Request; use Psr\Http\Server\MiddlewareInterface; use Psr\Http\Server\RequestHandlerInterface as Handler; use Slim\Views\Twig; class GlobalTwigVarsMiddleware implements MiddlewareInterface { protected $twig; public function __construct(Twig $twig) { $this->twig = $twig; } public function process(Request $request, Handler $handler): Response { // 从请求/Session中获取用户(示例) $session = $request->getAttribute('session'); $currentUser = $session->get('user') ? $session->get('user') : null; // 注入全局变量 $this->twig->addGlobal('current_user', $currentUser); // 还可以加请求相关的其他变量,比如当前路由信息 $this->twig->addGlobal('current_route', $request->getAttribute('route')->getName()); return $handler->handle($request); } }
然后把这个中间件注册到容器,并添加到Slim的中间件队列里:
// 在容器中注册中间件 GlobalTwigVarsMiddleware::class => function (ContainerInterface $container) { return new GlobalTwigVarsMiddleware($container->get(Twig::class)); }; // 在App初始化时添加中间件(注意顺序,要放在TwigMiddleware之前) $app->add(GlobalTwigVarsMiddleware::class); $app->add(TwigMiddleware::class);
方案3:利用Twig扩展实现复杂全局逻辑
如果你的通用模型需要结合自定义函数、过滤器,或者有更复杂的初始化逻辑,写一个Twig扩展是最好的选择:
创建扩展类:
use Twig\Extension\AbstractExtension; use Twig\TwigFunction; use Twig\TwigFilter; class AppTwigExtension extends AbstractExtension { protected $config; protected $user; public function __construct(Configuration $config, User $user) { $this->config = $config; $this->user = $user; } // 返回全局变量数组 public function getGlobals(): array { return [ 'app_config' => $this->config->getArray('app'), 'current_user' => $this->user, ]; } // 还可以添加自定义函数/过滤器(可选) public function getFunctions(): array { return [ new TwigFunction('get_site_name', function () { return $this->config->getString('app.site_name'); }), ]; } }
然后在容器里注册这个扩展,并加到Twig实例中:
// 注册扩展到容器 AppTwigExtension::class => function (ContainerInterface $container) { return new AppTwigExtension( $container->get(Configuration::class), $container->get(User::class) ); }; // 修改Twig的容器定义,添加扩展 Twig::class => function (ContainerInterface $container) { $config = $container->get(Configuration::class); $twigSettings = $config->getArray('twig'); $twig = Twig::create($twigSettings['path'], $twigSettings['settings']); // 添加自定义扩展 $twig->addExtension($container->get(AppTwigExtension::class)); return $twig; },
三种方案各有侧重,你可以根据自己的需求选:静态配置用方案1,请求相关数据用方案2,复杂全局逻辑用方案3~
内容的提问来源于stack exchange,提问作者Tobia
相关产品推荐
相关产品推荐

