Drupal 8 Temp Store

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 returnNULL
. 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 valuedelete($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 returnNULL
. 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 returnNULL
. 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. ReturnsTRUE
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.