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:
// 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');
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:
namespace Drupal\my_module; use Drupal\Core\Controller\ControllerBase; use Drupal\user\PrivateTempStoreFactory; class MyModuleController extends ControllerBase { protected $tempStore; // Pass the dependency to the object constructor public function __construct(PrivateTempStoreFactory $temp_store_factory) { // For "mymodule_name," any unique namespace will do $this->tempStore = $temp_store_factory->get('mymodule_name'); } // Uses Symfony's ContainerInterface to declare dependency to be passed to constructor public static function create(ContainerInterface $container) { return new static( $container->get('user.private_tempstore') ); } // Save some temporary data public function index() { $this->tempStore->set('my_variable_name', $some_data); // Do other stuff, return a render array, etc... } // Read some temporary data public function listPage() { $visited = $this->tempStore->get('my_variable_name'); // Do other stuff, return a render array, etc... } }
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:
// Save the data: $_SESSION['mymodule_name']['my_variable_name'] = $somedata; // Get the data: $somedata = $_SESSION['mymodule_name']['my_variable_name'];
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.