I recently needed to temporarily store information associated with a user's session in Drupal 8. In past versions of Drupal, I might have just thrown the data in $_SESSION
. In Drupal 8 there's a service for that; actually, two services: use user.private_tempstore
and user.shared_tempstore
for temporarily storing user-specific and non-user-specific data, respectively.
Background Reading
If you're new to Drupal 8, there are a number of OOP principles and specific Symfony concepts worth getting to know. This post does not directly address those. Here I'll just briefly address storing temporary data (aka writing to $_SESSION
). For more background, the following are a few good resources about OOP, dependency injection and services in Drupal 8 (or skip ahead directly to writing $_SESSION
variables in Drupal 8):
- Object Oriented Programming 101 - a great introductory to OOP principles by Larry Garfield on DrupalWatchDog.com, with (of course) a bit of a slant toward Drupal development
- Drupal 8 Dependency Injection, Service Container And All That Jazz - a nice overview of services and dependency injection
- Services and dependency injection in Drupal 8 - an overview of dependency injection in Drupal 8, from Drupal.org
Method One: Use "\Drupal::service()"
Statically calling user.private_tempstore
is simple and easy to use from just about anywhere within your application. It is especially useful for accessing the user.private_tempstore
service from within procedural code (i.e. any hook implementation or simple function in your application).
To set temporary data:
</p> <p>// For "mymodule_name," any unique namespace will do.<br /> // I'd probably use "mymodule_name" most of the time.<br /> $tempstore = \Drupal::service('user.private_tempstore')->get('mymodule_name');<br /> $tempstore->set('my_variable_name', $some_data);</p> <p>
To read temporary data:
</p> <p>$tempstore = \Drupal::service('user.private_tempstore')->get('mymodule_name');<br /> $some_data = $tempstore->get('my_variable_name');</p> <p>
Method Two: Use Dependency Injection
Within controller or plugin classes, use dependency injection and Symfony's ContainerInterface to inject
user.private_tempstore
as a dependency.Here's how to use dependency injection in a Drupal 8 controller:
<br /> namespace Drupal\my_module;</p> <p>use Drupal\Core\Controller\ControllerBase;<br /> use Drupal\user\PrivateTempStoreFactory;</p> <p>class MyModuleController extends ControllerBase {</p> <p> protected $tempStore;</p> <p> // Pass the dependency to the object constructor<br /> public function __construct(PrivateTempStoreFactory $temp_store_factory) {<br /> // For "mymodule_name," any unique namespace will do<br /> $this->tempStore = $temp_store_factory->get('mymodule_name');<br /> }</p> <p> // Uses Symfony's ContainerInterface to declare dependency to be passed to constructor<br /> public static function create(ContainerInterface $container) {<br /> return new static(<br /> $container->get('user.private_tempstore')<br /> );<br /> }</p> <p> // Save some temporary data<br /> public function index() {<br /> $this->tempStore->set('my_variable_name', $some_data);<br /> // Do other stuff, return a render array, etc...<br /> }</p> <p> // Read some temporary data<br /> public function listPage() {<br /> $visited = $this->tempStore->get('my_variable_name');<br /> // Do other stuff, return a render array, etc...<br /> }</p> <p>}<br />
For a real life example of a Drupal 8 class that uses dependency injection, check out \Drupal\user\Form\UserMultipleCancelConfirm in Drupal core.
Both methods are roughly equivalent to:
<br /> // Save the data:<br /> $_SESSION['mymodule_name']['my_variable_name'] = $somedata;</p> <p>// Get the data:<br /> $somedata = $_SESSION['mymodule_name']['my_variable_name'];<br />
But (and it's an important but) using Drupal 8 services provides needed abstraction and structure for interacting with a global construct. It's part of an overall architecture that allows developers to build and extend complex applications sustainably.