I want to submit a form and store the submitted values in the session. In Drupal 7 I just used $_SESSION['key'] = $value; but how do I correctly implement this in Drupal 8?

  • 1
    I'm not sure about this question. It's really vague, which generally isn't the sort of question we accept here. On the other hand, I can definitely see the same question showing up again and again, so perhaps it has enough value to stay. I've answered as well as I can below, but I'll also vote to close to see what the community thinks. – Letharion Oct 16 '14 at 19:01

Drupal 8 uses Symfony's HttpFoundation Session Management, so that's where the API is documented.

If you look in core.services.yml you can find that Drupal's wrapper is in.

  class: Drupal\Core\Session\SessionManager
  • Ok, I will be a bit more specific. I want to submit a form and then I want to store the submitted values in a session. In D7 I just used $_SESSION['key'] = $value. But how do I implement this in the correct way id D8? – Robin Oct 16 '14 at 19:14
  • @Robin sounds like you should open new questions, the issue here just gets more confused is you change the scope. The way I see it, there's two things you need to know. One is, "How do I get a hold of the session object in my form handlar", and the other is "How do I set state". The latter is sort of answered by this answer, although you could ask for more specifics in a new question. The former is DIC related, and requires a whole question on it's own. – Letharion Oct 16 '14 at 20:00
  • This is not correct session_manager is not the wrapper for the $_SESSION superglobal. The conversion to the symfony session is not yet complete, see drupal.org/node/1858196 and subissues. – znerol Oct 17 '14 at 11:18
  • @znerol I'm familiar with the issue, you'll find my nick in there a few times ;) Though I thought it was obsolete. If what you say is true, then what on earth does session_manager do? – Letharion Oct 17 '14 at 12:43
  • @Letharion: Session manager is a fancy wrapper around session_start and session_write_close, i.e. the equivalent to Symfony NativeSessionStorage + Drupal lazy initialization and mixed mode sessions (for the moment). This issue needs to land before we can get rid of $_SESSION. – znerol Oct 17 '14 at 13:31

In D8 the session data is provided by a symfony session object, which is attached to the request. See this comparison of D7 against D8:

Drupal 7:

function mymodule_session_counter_increment() {
  if (!isset($_SESSION['mymodule_count'])) {
    $_SESSION['mymodule_count'] = 0;

  return $_SESSION['mymodule_count']++;

Drupal 8:

class MymoduleSessionCounter {
  function increment(Request $request) {
    $session = $request->getSession();
    $value = $session->get('mymodule_count', 0);
    $session->set('mymodule_count', $value + 1);

    return $value;

Change record: Access session data through the Request object

Session management has not changed. You don't need to do anything, because Drupal starts a session for each request automatically and you can use it right away.

Examples how to get the session:


In procedural code get the request from the static wrapper \Drupal:

$request = \Drupal::request();
$session = $request->getSession();
$session->set('mymodule_value', $value);


In a controller you can pull the request from the route argument stack by including a typed request parameter. An example from UserController:

  public function resetPass(Request $request, $uid, $timestamp, $hash) {          
    $session = $request->getSession();
    $session->set('pass_reset_hash', $hash);
    $session->set('pass_reset_timeout', $timestamp);

It's not necessary to define the route parameter in the route definition. The request is always available.


In a form method get the request from getRequest():

  public function submitForm(array &$form, FormStateInterface $form_state) {
    $session = $this->getRequest()->getSession();
    $session->set('mymodule_form_value', $form_state->getValue('value'));

Private Tempstore

The private tempstore is not a replacement for sessions. It depends on the session id and it's not possible to use it without a session. So you can store the values directly in the session as well. Drupal core uses the private tempstore for big amount of data and only for authenticated users who already have a session. For anonymous users it's not easy to get a private tempstore started, because drupal uses dummy session id's until it starts a real session. If you start a private tempstore in custom code it has the wrong session id.

  • You say, "It's not necessary to define the route parameter in the route definition. The request is always available." But I get a runtime exception: Controller "...\Controller\MatomoReportsController::reports()" requires that you provide a value for the "$request" argument. Either the argument is nullable and no null value has been provided, no default value has been provided or because there is a non optional argument after this one. in Symfony\Component\HttpKernel\Controller\ArgumentResolver->getArguments() (line 78 of /var/www/vendor/symfony/http-kernel/Controller/ArgumentResolver.php). – shelane Jan 22 '20 at 18:44

Here is an article on how to use the appropriate service to store data in the session: http://atendesigngroup.com/blog/storing-session-data-drupal-8

There are two methods described in the article, here's the first one which doesn't use dependency injection. (code is not mine)

To set temporary data:

// For "mymodule_name," any unique namespace will do.
// I'd probably use "mymodule_name" most of the time.
$tempstore = \Drupal::service('user.private_tempstore')->get('mymodule_name');
$tempstore->set('my_variable_name', $some_data);

To read temporary data:

$tempstore = \Drupal::service('user.private_tempstore')->get('mymodule_name');
$some_data = $tempstore->get('my_variable_name');

To temporary store data in the session, in Drupal 8.5 and higher there is the tempstore.private service that, for example, is used from the node edit form to temporary store the node preview.

  public function form(array $form, FormStateInterface $form_state) {

    // Try to restore from temp store, this must be done before calling
    // parent::form().
    $store = $this->tempStoreFactory

    // Attempt to load from preview when the uuid is present unless we are
    // rebuilding the form.
    $request_uuid = \Drupal::request()->query
    if (!$form_state
      ->isRebuilding() && $request_uuid && ($preview = $store
      ->get($request_uuid))) {

      /** @var $preview \Drupal\Core\Form\FormStateInterface */

      // Rebuild the form.

      // The combination of having user input and rebuilding the form means
      // that it will attempt to cache the form state which will fail if it is
      // a GET request.
      $this->entity = $preview
      $this->entity->in_preview = NULL;
        ->set('has_been_previewed', TRUE);

    /** @var \Drupal\node\NodeInterface $node */
    $node = $this->entity;
    if ($this->operation == 'edit') {
      $form['#title'] = $this
        ->t('<em>Edit @type</em> @title', [
        '@type' => node_get_type_label($node),
        '@title' => $node

    // ...


   * Form submission handler for the 'preview' action.
   * @param $form
   *   An associative array containing the structure of the form.
   * @param $form_state
   *   The current state of the form.
  public function preview(array $form, FormStateInterface $form_state) {
    $store = $this->tempStoreFactory
    $this->entity->in_preview = TRUE;
      ->uuid(), $form_state);
    $route_parameters = [
      'node_preview' => $this->entity
      'view_mode_id' => 'full',
    $options = [];
    $query = $this
    if ($query
      ->has('destination')) {
      $options['query']['destination'] = $query
      ->setRedirect('entity.node.preview', $route_parameters, $options);

Before Drupal 8.5, the service is user.private_tempstore, which will be removed in Drupal 9.0.

Since you want to store the submitted values, which I assume are used only for a limited period of time and aren't necessary anymore after the user logs in or logs out, I would use the same approach used from Drupal core to show a preview of a node before it gets created/saved. It has also the pro that deleting the data is automatically done.


Sessions (Drupal 8) are used via the simple Session implementation of SessionInterface interface.

Symfony sessions are designed to replace several native PHP functions. Applications should avoid using session_start(), session_regenerate_id(), session_id(), session_name(), and session_destroy() and instead use the APIs in the following section.

Sessions Drupal 8


use Symfony\Component\HttpFoundation\Session\Session;

$session = new Session();

// set and get session attributes
$session->set('name', 'Yash');

// set flash messages
$session->getFlashBag()->add('notice', 'Profile updated');

// retrieve messages
foreach ($session->getFlashBag()->get('notice', array()) as $message) {
    echo '<div class="flash-notice">'.$message.'</div>';
  • 1
    You don't need to instantiate a session object or start a session. Drupal adds a session to each request in the bootstrap process in Drupal\Core\StackMiddleware\Session::handle() and starts the session. You can get it with $session = \Drupal::request()->getSession(). – 4k4 May 31 '17 at 18:19

You can use "\Drupal::service()".

To set temporary data:

$tempstore = \Drupal::service('user.private_tempstore')->get('mymodule_name');
$tempstore->set('my_variable_name', $some_data);

To read temporary data:

$tempstore = \Drupal::service('user.private_tempstore')->get('mymodule_name');
$some_data = $tempstore->get('my_variable_name');

You can refer to this tutorial for more details.


Before you go rolling your own, see if the Session Node Access module does what you need.


how about ? :

    $session = new Session();
    $session->set('key', 'value');

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

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.