Storing Session Data with Drupal 8

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):

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.

Drupal 8 Drupal

Read This Next