Preciel
Preciel

Reputation: 2837

How to use session in Symfony

I'm getting a hard time trying to understand how symfony session works.
And couldn't find the answer I'm looking for here on S.O. or other external sources.

[SETTINGS]

[THE PROBLEM]

Quite easy to understand, I just can't figure out where to start my session. What I did for now was create this action in SiteController

public function sessionAction(Request $request) {
    $em=$this->getDoctrine()->getManager();
    $site=$em->getRepository('SiteBundle:Site')->findOneBy(array('url'=>$request->getSchemeAndHttpHost()));
    if($site) {
        $session=new Session();
        $session->set('id',$site->getId());
        $session->set('url',$site->getUrl());
        $session->set('name',$site->getName());
    } else {
        [...]
    }
}

How can I call this function on website loading to create the session?

Also, is it the right way to do it?

Upvotes: 2

Views: 5178

Answers (2)

Preciel
Preciel

Reputation: 2837

Well, first a big thanks to Gopal Joshi who helped me figure out a lot of things... :)

For those who come later, read his answer, it's helpful in a lot of ways...
I would also suggest reading this question, it goes in pair with the current question.

Meanwhile, I came out with this:

1: Register the service

AppBundle\Resources\config\services.yml

app.session_handler:
    class: SalonBundle\Services\SessionHandler
    arguments:
        - "@doctrine"
        - "@router"
    tags:
        - { name: kernel.event_listener, event: kernel.request, method: setSession }

First, I will point that I use the argument @router, but unless you need to redirect the response to another url, it's not needed.

2: Create the service

AppBundle\EventListener\SessionHandler.php

<?php

namespace AppBundle\EventListener;

use Doctrine\Bundle\DoctrineBundle\Registry;
use Symfony\Bundle\FrameworkBundle\Routing\Router;
use Symfony\Component\HttpFoundation\RedirectResponse;
use Symfony\Component\HttpKernel\Event\GetResponseEvent;

class SessionHandler {

    private $doctrine;
    private $router;

    public function __construct(Registry $doctrine, Router $router) {
        //Make sure to type $doctrine and $router in the constructor.
        //Else some methods can't be found directly, and Symfony have to do the job for you
        //I guess it would make a big project a bit slower without the types
        $this->doctrine=$doctrine;
        $this->router=$router;
    }

    public function setSession(GetResponseEvent $responseEvent) {
        //This function parameter call on GetResponseEvent class
        //for the same reason as above.
        $site=$this->doctrine->getRepository('AppBundle:Site')->findOneBy(array('url'=>$responseEvent->getRequest()->getSchemeAndHttpHost()));
        if($site) {
            $session=$responseEvent->getRequest()->getSession();
            $session->clear();
            $session->set('site', $site);
        } else {
            if($responseEvent->getRequest()->get('_route') != 'some_route') {
                //This next line is the only reason as to why we pass "@router" as argument
                $responseEvent->setResponse(new RedirectResponse($this->router->generate('some_route')));
            }
        }
    }
}

To sum things up, it's very close to Gopal Joshi answer...
In fact, it's the same, just with some code cleanup...
Both his answer and mine are working...
The only difference is that mine won't show warning like:
Method 'methodName()' not found or import 'import\path\and\name' is never used

Gopal Joshi, if you happen to read my answer, I'm asking you, which one should I validate?
Being honest here, most of the credits is yours, so I will validate the answer you want... ;)

Upvotes: 4

Gopal Joshi
Gopal Joshi

Reputation: 2358

One way of getting Sessions from controller is:

$session = $this->get("session");

Setter: $session->set('id','<value>');

Getter: $session->get('id');

Full Code

public function sessionAction(Request $request) {
    $em = $this->getDoctrine()->getManager();
    $site = $em->getRepository('SiteBundle:Site')->findOneBy(array('url'=>$request->getSchemeAndHttpHost()));
    if($site) {
        $session = $this->get("session");
        $session->set('id',$site->getId());
        $session->set('url',$site->getUrl());
        $session->set('name',$site->getName());
    } else {
        [...]
    }
}

Update-1:

Create service to set session variables

AppBundle\EventListener\SessionHandler.php

<?php

namespace AppBundle\EventListener;

use Symfony\Component\HttpFoundation\Request;
use Symfony\Component\Routing\Router;
use Symfony\Component\HttpKernel\Event\GetResponseEvent;
use Symfony\Component\HttpFoundation\RedirectResponse;

class SessionHandler {

    private $doctrine;
    private $container;
    private $router;

    public function __construct($doctrine, $router, $container) {
        $this->doctrine  = $doctrine;
        $this->router    = $router;
        $this->container = $container;
    }

    public function setSession() {
        $route = $this->container->get('request')->get('_route');
        $site = $this->doctrine->getRepository('SiteBundle:Site')->findOneBy(array('url' => $route->getUri()));
        if($site) {
            $session = $this->container->get("session");
            $session->set('id',$site->getId());
            $session->set('url',$site->getUrl());
            $session->set('name',$site->getName());
        } else {
            [...]
        }
    }
}

AppBundle\Resources\config\services.yml

Option-1

Call setSession() function on each page load event.

session_handler:
        class: AppBundle\EventListener\SessionHandler
        arguments: [@doctrine, @router, @service_container]
        tags:
            - {name: kernel.event_listener, event: kernel.request, method: setSession} 

Option-2

Call setSession() function manually where you need to set session.

session_handler:
        class: AppBundle\EventListener\SessionHandler
        arguments: [@doctrine, @router, @service_container]
        tags:
            - {name: kernel.event_listener }

Call setSession() function from controller

$sessionService = $this->get('session_handler');
$sessionService->setSession();

Upvotes: 0

Related Questions