Drupal 8 Temp Store

Header Image

One of the most powerful, flexible, and agile CMS available, Drupal 8 possesses some unique functionalities like Temp store. Let’s take a look at Temp store and how to take advantage of its power.

Temp store allows you to temporarily store any data. This data storage exists in $_SESSION. Because this storage is tied, as a rule, to a user, it does not use $_SESSION and stores everything inside the system or in the database.

There are two services in the kernel for the temporary storage: tempstore.private and tempstore.shared. They work identically, but tempstore.private always stores data for a specific user. For example, a call with one key at a private store will give different data for each user. On the other hand, tempstore.shared is accessible from under each user.

The scope of these services and their storages can be massive.

You can store some temporary values of forms.

If the user did not save the forms, you can restore the storage data in both ordinary and REST forms.

You can integrate forms controlled outside Drupal, or on React or Vue.

These storages work for both authorized and anonymous users. For anonymous users, the owner has session_id(). For authorized users, the owner has uid.

Values in these storages live 604800 seconds (1 week) by default, after which they are automatically deleted. In order to change this value, we need to connect sites/default/services.yml and override it:

parameters:
  # 10 Seconds
  tempstore.expire: 10

Let’s look at the capabilities of tempstore.private and tempstore.public. Although they are similar, they are slightly different.

Private storage: tempstore.private

This storage is private for each user, and has the following methods:

  • get($key): Gets the value from the store by its key. If there is no data, it will return NULL. If there is data, it will return a value.
  • set($key, $value): Writes to the store the value of $ value under the key $ key.
  • getMetadata($key): Returns metadata for a specific $ key, without data. This object contains the owner property, where the value is stored, and who the value belongs to, while the updated property is a unix timestamp for recording this value
  • delete($key): Deletes data associated with the key $ key from the storage.

Shared storage: tempstore.shared

This storage is shared, and may contain data common to all users. The store has the following methods:

  • get($key): Gets the value from the store by its key. If there is no data, it will return NULL. If there is data, it will return a value.
  • getIfOwner($key): Gets the value from the store by its key. If there is no data or the data was not written from under the current user, it will return NULL. If there is and the value was written from under the current user, it will return a value.
  • setIfNotExists($key, $value): Writes to the store the value of $ value under the key $ key, only if at the moment there is no data on this key. Returns TRUE if written, FALSE if data already existed.
  • setIfOwner($key, $value): Writes to the store the value of $ value under the key $key, only if there is currently no data, or the owner of the current data is the current user.
  • set($key, $value): Writes to the store the value of $ value under the key $key.
  • getMetadata($key): Returns metadata for a specific $key, without data. This is an object containing the owner property, in which the value is stored, to whom the value belongs, and the updated property is a unix time stamp for recording this value.
  • delete($key): Deletes data associated with this key $key from the storage.
  • deleteIfOwner($key): Deletes data associated with this $key` from the repository only if the data belongs to the current user.

How to Call temp.store

First, the tempstore of the desired storage is obtained, then the “collection” is obtained from the storage, where the data is stored under the necessary keys. Typically, the name of a “collection” equals the name of the module.

use Drupal\Core\TempStore\PrivateTempStoreFactory;
use Drupal\Core\TempStore\SharedTempStoreFactory;

/** @var PrivateTempStoreFactory $private_tempstore */
$private_tempstore = \Drupal::service('tempstore.private');
$dcont_private_storage = $private_tempstore->get('dcont');
$dcont_private_storage->set('username', 'Drupal');

/** @var SharedTempStoreFactory $shared_tempstore */
$shared_tempstore = \Drupal::service('tempstore.shared');
$dcont_shared_storage = $shared_tempstore->get('dcont');
$dcont_shared_storage->set('username', 'Drupal');

In the example, we will create a form on the /dcont-temp-store-form page with two fields, one of which will store the message in private storage, and the other in shared. First, create a form:

src/FormWithTempStore.php
<?php

namespace Drupal\dcont\Form;
use Drupal\Core\Form\FormBase;
use Drupal\Core\Form\FormStateInterface;
use Drupal\Core\TempStore\PrivateTempStoreFactory;
use Drupal\Core\TempStore\SharedTempStoreFactory;
use Symfony\Component\DependencyInjection\ContainerInterface;

/**
 * Provides a dcont form.
 */
class FormWithTempStore extends FormBase {
  /**
   * Private storage.
   *
   * @var PrivateTempStoreFactory
   */
  protected $privateTempStore;

  /**
   * Shared storage.
   *
   * @var SharedTempStoreFactory
   */
  protected $sharedTempStore;

  /**
   * Constructs a FormWithTempStore object.
   */
  public function __construct(PrivateTempStoreFactory $private_temp_store, SharedTempStoreFactory $shared_temp_store) {
    $this->privateTempStore = $private_temp_store->get('dcont');
    $this->sharedTempStore = $shared_temp_store->get('dcont');
  }

  /**
   * {@inheritdoc}
   */
  public static function create(ContainerInterface $container) {
    return new static(
      $container->get('tempstore.private'),
      $container->get('tempstore.shared')
    );
  }

  /**
   * {@inheritdoc}
   */
  public function getFormId() {
    return 'form_with_temp_store';
  }

  /**
   * {@inheritdoc}
   */
  public function buildForm(array $form, FormStateInterface $form_state) {
    $form['private_message'] = [
      '#type' => 'textarea',
      '#title' => $this->t('Private message'),
      '#required' => TRUE,
      '#description' => $this->t('This value will be private for each user.'),
      '#default_value' => $this->privateTempStore->get('message'),
    ];
    $form['shared_message'] = [
      '#type' => 'textarea',
      '#title' => $this->t('Shared message'),
      '#required' => TRUE,
      '#description' => $this->t('This value will be shared for all users.'),
      '#default_value' => $this->sharedTempStore->get('message'),
    ];
    $form['actions'] = ['#type' => 'actions'];
    $form['actions']['submit'] = [
      '#type' => 'submit',
      '#value' => $this->t('Save'),
    ];

    return $form;
  }

  /**
   * {@inheritdoc}
   */
  public function submitForm(array &$form, FormStateInterface $form_state) {
    $this->privateTempStore->set('message', $form_state->getValue('private_message'));
    $this->sharedTempStore->set('message', $form_state->getValue('shared_message'));
  }
}

Using the ContainerInjectionInterface which implements FormBase, we pass the service containers we need in the static create() method and accept them with construct(). Next, we write them into the properties, immediately getting the “collection” of the same name as the module.

In the form, we created two fields for entering messages, the default values for which are taken from the corresponding storages. As we click the Save button, we write the current field values to the corresponding storages. We just need to declare a route for this form.

dcont.routing.yml

dcont.form.temp_store:
  path: '/dcont-temp-store-form'
  defaults:
    _title: 'Example form with temp storage'
    _form: 'Drupal\dcont\Form\FormWithTempStore'
  requirements:
    _permission: 'access content'

That’s all! Clear the cache and visit the page. You will have a form with two fields. Everything that you enter in tempstore.shared will be visible to all users, they will also be able to change this message and it will change for everyone at the time of the next generation of the form. For private values, each user will have personal ones.

I hope this helps you to use temp.store in the future, as well as improves your code.

Category:

Do you need Drupal contractors to meet demand?

Hire pre-screened, expert Drupal contractors. Our platform is part of the Esteemed Talent Network. We provide world-class Drupal talent that brands can trust — through tools they already use. We work as an extension of our clients in close collaboration to provide vetted architects, developers, designers and digital professionals.

If you need help hiring for digital, or to scale up to meet demand, please let us know. We'll be happy to get you started with a custom Esteemed subscription plan..