如何将全局变量注入所有模板?

How to inject global variables into all templates?

在我的 twig 模板中,每个页面都需要一些变量,例如 userNameuserIduserImage

将它们注入模板的最佳方法是什么?

我已经阅读了文章 How to Inject Variables into all Templates,但是如何将变量(例如当前用户)写入 config/packages/twig.php 文件?

现在每个控制器中都有这样的代码:

return $this->render('admin/users/index.html.twig', [
   "allUsers" => $allUsers,
   "pageTitle" => "Benutzerübersicht",
   "userName" => "Max Mustermann",
   "userId" => 5,
   "userImage" => "http://i.pravatar.cc/150?img=6"
]);

(这些只是示例值,因为我还没有集成身份验证但想创建我的模板)

有没有比在每个控制器中注入每个变量更好的方法?

您有多种选择,具体取决于您的需要:

###您可以使用事件侦听器将其作为 Twig 全局变量注入。

  1. 创建监听器class:
namespace App\Listener;
// src/EventListener/ControllerListener.php

use Doctrine\ORM\EntityManager;
use Symfony\Component\HttpKernel\Event\FilterControllerEvent;
use Symfony\Component\Security\Core\Security;
use Twig\Environment;

class ControllerListener {
    /**
     * @var \Twig\Environment
     */
    private $twig;
    /**
     * @var \Doctrine\ORM\EntityManager
     */
    private $manager;
    /**
     * @var \Symfony\Component\Security\Core\Security
     */
    private $security;

    public function __construct( Environment $twig, EntityManager $manager, Security $security ) {
        $this->twig     = $twig;
        $this->manager  = $manager;
        $this->security = $security;
    }

    public function onKernelController( FilterControllerEvent $event ): void {
        $results = $this->manager->getRepository( 'SomeClass' )->findBy( [ 'some' => 'criteria' ] );
        $user    = $this->security->getUser();
        $this->twig->addGlobal( 'veryGlobal', $results[0]->getName() );
        $this->twig->addGlobal( 'username', $user->getUsername() );
    }
}

我正在注射:

  • Twig,所以你可以在那里添加全局变量。
  • 实体管理器,因此如果您需要从那里获取信息,您可以查询数据库
  • 安全,从用户那里获取信息。
  1. 创建完成后,需要添加以下配置行:
# config/services.yaml
services:
    App\EventListener\ControllerListener:
        tags:
            - { name: kernel.event_listener, event: kernel.controller }

这将使事件侦听器能够对每个请求 运行。

使用 twig 配置注入全局服务:

使用这些配置行,如 documentation 中所述,您可以告诉 twig 注入特定服务:

# config/packages/twig.yaml
twig:
    # ...
    globals:
        # the value is the service's id
        users: '@App\Service\UserManagement'

那么就很简单了,创建App\Service\UserManagement:

namespace App\Service:

class UserManagement {

   public function __construct() {
      // use the constructor to inject your dependencies, as usual
   }

   public function getOldestUser() {
      // do your thing
      return $oldestUserName;
   }
}

然后从树枝你可以做:

{{ users.oldestUser }}

注意 每次您调用 users.OldestUser 时都会执行该方法,这可能会占用大量资源,具体取决于您在做什么。将该服务的结果缓存在本地 属性 上可能是个好主意。

最后,如果您只对登录用户数据感兴趣

正如其他人提到的,如果您只对属于登录用户的数据感兴趣,您可以简单地访问它 through the app variable, which is injected on each request

The representation of the current user or null if there is none. The value stored in this variable can be a UserInterface object, any other object which implements a __toString() method or even a regular string.

例如:

{{ app.user.userName }}

你在实现用户界面吗?如果是这样,您可以按照 https://symfony.com/doc/current/templating/app_variable.html

中的说明使用 app.user

例如在您的模板中,您可以使用 {{ app.user.userName }} 来显示当前登录用户的用户名。