Reputation: 1191
I have read about Namespaced Attributes. I try to use this feature :
#src/Controller/CartController.php
public function addProduct(int $cart_id, int $product_id, Request $request, SessionManager $sessionManager)
{
$session = new Session(new NativeSessionStorage(), new NamespacedAttributeBag());
$session->set("cart_$cart_id/product_$product_id", $request->get('selected_product_qty'));
dump($session);
die();
}
It work well.
So as an improvement, I want to override the session services, so it'll use namespacedattributebag
everywhere and it use Depency Injection instead of coupling Session service into addProduct function.
To do this I edit my services.yaml
#config/services.yaml
session:
public: true
class: Symfony\Component\HttpFoundation\Session\Session
arguments: ['@session.storage', '@session.namespacedattributebag']
session.namespacedattributebag:
class: Symfony\Component\HttpFoundation\Session\Attribute\NamespacedAttributeBag
And then I update CartController
:
public function addProduct(int $cart_id, int $product_id, Request $request, Session $session)
{
$session->set("cart_$cart_id/product_$product_id", $request->get('selected_product_qty'));
dump($session);
die();
}
Now I got the following error message :
Circular reference detected for service "session", path: "session -> session.flash_bag -> session".
This error should have been solved in this issue : #36261 It have been discussed here.
But for me the problem still present... (I am using Symfony 5.1)
Upvotes: 4
Views: 876
Reputation: 1191
I can't provide more explanation (unfortunately) but if this problem occurs, you have to explicitely define the third (and optionnal parameter) of Session
constructor :
#config/services.yaml
session:
public: true
class: Symfony\Component\HttpFoundation\Session\Session
arguments: ['@session.storage', '@session.namespacedattributebag', '@session.flash_bag']
session.namespacedattributebag:
class: Symfony\Component\HttpFoundation\Session\Attribute\NamespacedAttributeBag
I think this is because of the following code :
#src/Symfony/Bundle/FrameworkBundle/DependencyInjection/Compiler/SessionPass.php
foreach ($container->getDefinition('session')->getArguments() as $v) {
if (!$v instanceof Reference || !isset($bags[$bag = (string) $v]) || !\is_array($factory = $bags[$bag]->getFactory())) {
continue;
}
if ([0, 1] !== array_keys($factory) || !$factory[0] instanceof Reference || 'session' !== (string) $factory[0]) {
continue;
}
if ('get'.ucfirst(substr($bag, 8, -4)).'Bag' !== $factory[1]) {
continue;
}
$bags[$bag]->setFactory(null);
}
You'll see that if you debug it :
dump($bags);
foreach($container->getDefinition('session')->getArguments() as $v){...}
dump($bags);
And having your config like this :
#config/services.yaml
...
arguments: ['@session.storage', '@session.namespacedattributebag', '@session.flash_bag']
...
You'll notice that debug show :
"session.flash_bag" => Symfony\Component\DependencyInjection\Definition {#2253 ▼
-class: "Symfony\Component\HttpFoundation\Session\Flash\FlashBag"
-file: null
-factory: array:2 [▶]
For the input services Definition
of flash_bag
And then in output (Second dump()
) :
"session.flash_bag" => Symfony\Component\DependencyInjection\Definition {#2253 ▼
-class: "Symfony\Component\HttpFoundation\Session\Flash\FlashBag"
-file: null
-factory: null
The factory
parameter is null.
So I guess that in this case flash_bag
object isn't created, and so, there is no Circular reference
...
I can't explain it more.
Plus, someone from Symfony staff said : @warslett commented on 28 Mar
@ekosogin you don't actually need the @session.flash_bag parameter on there. You should be able to do this:
session: class: Symfony\Component\HttpFoundation\Session\Session arguments: - '@session.storage' - '@Symfony\Component\HttpFoundation\Session\Attribute\NamespacedAttributeBag' Symfony\Component\HttpFoundation\Session\Attribute\NamespacedAttributeBag: ~```
But actually, I think this is wrong as it'll not work if you don't put the @session.flash_bag parameter as he say.
Hope it'll help.
Upvotes: 3