Reputation: 867
I want to add an extra bag to symfony session.
I do that in compiler pass:
public function process(ContainerBuilder $container)
{
$bag = new AttributeBag("my_session_attributes");
$container->getDefinition("session")
->addMethodCall("registerBag", [$bag]);
}
But i get an exception with message:
Unable to dump a service container if a parameter is an object or a resource.
Here is the trace stack:
- in XmlDumper.php line 379
- at XmlDumper::phpToXml(object(AttributeBag)) in XmlDumper.php line 328
- at XmlDumper->convertParameters(array(object(AttributeBag)), 'argument', object(DOMElement)) in XmlDumper.php line 94
- at XmlDumper->addMethodCalls(array(array('registerBag', array(object(AttributeBag)))), object(DOMElement)) in XmlDumper.php line 183
- at XmlDumper->addService(object(Definition), 'session', object(DOMElement)) in XmlDumper.php line 272
- at XmlDumper->addServices(object(DOMElement)) in XmlDumper.php line 52
- at XmlDumper->dump() in ContainerBuilderDebugDumpPass.php line 34
- at ContainerBuilderDebugDumpPass->process(object(ContainerBuilder)) in Compiler.php line 104
- at Compiler->compile(object(ContainerBuilder)) in ContainerBuilder.php line 598
- at ContainerBuilder->compile() in Kernel.php line 514
- at Kernel->initializeContainer() in Kernel.php line 133
- at Kernel->boot() in Kernel.php line 182
- at Kernel->handle(object(Request)) in app_dev.php line 29
How should I add new bag if I can't pass object arguments in service definitions?
Upvotes: 2
Views: 2327
Reputation: 1
Another approach would be to add a new AttributeBag through an EventListener.
Something like this:
<?php
namespace App\EventListener;
use Symfony\Component\HttpKernel\Event\RequestEvent;
use Symfony\Component\HttpFoundation\Session\Attribute\AttributeBag;
use Symfony\Component\HttpFoundation\Session\SessionInterface;
class AddSessionAttributeBagListener
{
/**
* @param RequestEvent $event
*/
public function onKernelRequest(RequestEvent $event)
{
if (!$event->isMainRequest()) {
return;
}
$session = $event->getRequest()->getSession();
$bag = new AttributeBag('metrics');
$bag->setName('metrics');
$session->registerBag($bag);
}
}
When registering the event listener, set priority to make sure it's executed at the right moment
app.event_listener.add_session_attribute_bag:
class: App\EventListener\AddSessionAttributeBagListener
tags:
- { name: kernel.event_listener, event: kernel.request, method: onKernelRequest, priority: 127}
Upvotes: 0
Reputation: 900
This matter is not clear in doc, your example helped a bit but I think there is a more clean way to add a bag to symfony session, here is what I did (symfony 4+)
Add a bag class, for instance you can extends the AttributeBag one
namespace App\Tracking;
use Symfony\Component\HttpFoundation\Session\Attribute\AttributeBag;
class TrackingBag extends AttributeBag
{
public function __construct(string $storageKey = 'trackings')
{
parent::__construct($storageKey);
$this->setName($storageKey);
}
}
Then add a CompilerPass
public function process(ContainerBuilder $container)
{
$container->getDefinition("session")->addMethodCall(
"registerBag",
[new Reference('App\\Tracking\\TrackingBag')]
);
}
Then you can use it like that in twig
{{ app.session.bag('trackings').all }}
I still believe there is cleaner way but this was the only one which worked for me.
Upvotes: 1
Reputation: 867
Ok, just after posting the question I had an idea which I consider a workaround but it works.
The AttributeBag has to be registered as service too:
public function process(ContainerBuilder $container)
{
$bagDefinition = new Definition();
$bagDefinition->setClass(AttributeBag::class);
$bagDefinition->addArgument("my_session_attributes");
$bagDefinition->addMethodCall("setName", ["my_session_attributes"]);
$bagDefinition->setPublic(false);
$container->setDefinition("my_session_attributes_service", $bagDefinition);
$container->getDefinition("session")
->addMethodCall("registerBag", [new Reference("my_session_attributes_service")]);
}
Upvotes: 2