php - 通过 CompilerPass 注册自定义 AttributeBag

标签 php symfony

我正在尝试通过将自定义 AttributBags 集成到 session 中来整理我的 session 变量。在 Symfony < 6.0 中,您可以将自定义 AttributBag 注入(inject)到 session 服务中。

查看相关问题

然而,这种方法在 Symfony >= 6.0 中不再有效。这blog article说明 session 服务已弃用,现在必须通过 request_stack 服务访问。对于 Controller ,这工作正常。

我当前(无效)的方法如下所示:定义自定义 AttributBag 类。

class ShoppingCartBag extends AttributeBag {
    public function __construct(string $storageKey = 'shoppingCart') {
        parent::__construct($storageKey);
    }
}

在 Kernel 类中添加自定义 CompilerPass,以便 Symfony 在构建容器时处理所有更改。

class Kernel extends BaseKernel {
    use MicroKernelTrait;

    protected function build(ContainerBuilder $container): void {
        $container->addCompilerPass(new AddShoppingCartBagToSessionService());
    }
}

自定义 CompilerPass 如下所示。

class AddShoppingCartBagToSessionService implements CompilerPassInterface {

    public function process(ContainerBuilder $container) {
        $container->getDefinition('request_stack') //<- Works, but how to access the session?
            ->addMethodCall('getSession') // How to bridge the gap? This thought does not work. I assume it is because the session is not yet instantiated when the container is build.
            ->addMethodCall('registerBag', [new Reference('App\Session\CustomBag\ShoppingCartBag')]);
    }
}

最佳答案

正如您正确假设的那样,通过编译器传递执行此操作时 session 尚不存在。

Symfony 使用一个所谓的 SessionFactory创建 session 。所以你可以做的是用你自己的 SessionFactoryInterface 实现装饰现有的 session.factory 服务,并在那里添加你的属性包:

这个装饰 session 工厂的实现可能如下所示:

namespace App;

use Symfony\Component\HttpFoundation\Session\SessionFactoryInterface;
use Symfony\Component\HttpFoundation\Session\SessionInterface;

class SessionFactoryWithAttributeBag implements SessionFactoryInterface
{
    public function __construct(private SessionFactoryInterface $delegate)
    {
    }

    public function createSession(): SessionInterface
    {
        $session = $this->delegate->createSession();
        $session->registerBag(new ShoppingCartBag());

        return $session;
    }
}

然后你可以通过services.yaml装饰session.factory:

services:
    App\SessionFactoryWithAttributeBag:
        decorates: session.factory
        arguments: ['@.inner']

现在,无论何时创建 session ,您的自定义包也会被注册

关于php - 通过 CompilerPass 注册自定义 AttributeBag,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/70577264/

相关文章:

Symfony2 功能测试以选择复选框

php - Symfony 2.7 缓存 :clear command checks every database connection

javascript - 如何使用 Symfony Webpack Encore 编译多个 javascript 文件?

php - Symfony2 : debug controller variables

php - 无法将 PHP 连接到 XAMPP 数据库以发送数据

php - 允许将标点符号提交到 MySQL 数据库

php - 如何在 php 和 sql 中创建聊天对话列表?

数组元素的PHP组合

php - 可以改进此 PHP 代码吗?

php - 将 SQL 查询 (+JOIN) 转换为 Symfony Propel 查询