I have developed a cart system in symfony2, and one thing that I wanted to do is storing items in the cart while you are logged out in session (or cookies, as you like) and when the user logs in, merge the existing cart user may have, with the session one. How to do that is yet to be decided (in business logic terms) but the skeleton on how to do that is what I’m going to explain:
First of all, Symfony2 has a nice event system that launches events in lots of points in the application. One of those is when a user logs in.
So in my Cart bundle, I have to define a service that will be listening to this event. First of all, I did that in src/Namespace/CartBundle/Resources/config/services.yml
(note that you have to load this configuration in Bundle’s DependencyInjection, which symfony already does if you create the bundle with the command line tool).
I configured the service as follows:
services:
# name of the service (a namespace, dot and the name separated by underscores)
cart.login_listener:
# this will be the Listener class, saved in a Listener Directory for better readability,
# but can be stored anywhere.
# naming conventions say that the classname should be suffixed with Listener
class: Namespace\CartBundle\Listener\LoginListener
# this is optional - you can give the listener other services as parameters. I needed
# doctrine, session, service_container (to get user) and my own service called cart.session which
# handles storing the cart in session and retrieving it.
arguments: [ @doctrine, @session, @service_container, @cart.session ]
# this three parameters are required.
# - The name is for this service to know that will be listening events.
# - The event name is in this case the security component
# - The method is the name of the method that we will implement in LoginListener class
tags:
- { name: kernel.event_listener, event: security.interactive_login, method: onLogin }
Once we have our service defined, we have to implement it. As we defined, we create the class in Namespace/CartBundle/Listener/LoginListener.php
<?php
namespace Namespace\CartBundle\Listener;
use Namespace\CartBundle\Entity\Cart;
use Symfony\Component\Security\Http\Event\InteractiveLoginEvent;
use Symfony\Bundle\DoctrineBundle\Registry as Doctrine;
use Symfony\Component\HttpFoundation\Session;
class LoginListener
{
protected $doctrine;
protected $session;
protected $sessionCart;
protected $container;
public function __construct(Doctrine $doctrine, Session $session, $container, $sessionCart )
{
$this->doctrine = $doctrine;
$this->session = $session;
$this->sessionCart = $sessionCart;
$this->container = $container;
}
public function onLogin(InteractiveLoginEvent $event)
{
$em = $this->doctrine->getEntityManager();
$user = $this->container->get('security.context')->getToken()->getUser();
//your stuff here...
}
}
Now the onLogin method will be called every time a user logs in. So we can do whatever we want, in my case the cart merging.