3

Imagine I have a hard to compute function or value.

$my_heavy_value = function($val) { // Hard to compute value. return strtoupper($val); };

What's the difference at performance level between these two?

  • $my_val = &drupal_static($my_heavy_value);
  • $my_val = \Drupal::state('my_val', $my_heavy_value);

Which one is stored in database? Is there one that is stored in memory? Is there a recommended one?

8

They perform different tasks.

drupal_static() only stores data for the current page load (or ajax load). For example, if you are loading something from a database table multiple times on a single page load (ie - a user account), the first time it is loaded it is saved to memory, and the next time it is needed, it is pulled from memory, rather than reloading it from the database, saving that second database query.

Drupal::state() saves data to the database, where it can be recovered in future requests. It's a cache of sorts.

You can actually use them in conjunction with each other as follows:

function get_some_value()
{
  // Instatiate the static
  $value = &drupal_static(__FUNCTION__);
  // Check if the value has already been set in this page load
  if(is_null($value))
  {
    // The value has not yet been set for this page load,
    // so retrieve it from the state if it exists, and if it
    // does, then save that to the static
    $value = \Drupal::state()->get('my_value');
    // Check if the value was retrieved from the state
    if(!$value)
    {
      // The value was not retrieved from the state, so
      // it needs to be generated. Below is an example
      // fetching it from the database
      $value = db_query('SELECT some_value FROM {some_table} WHERE some_column = :some_value', [':some_value' => 'some value'])->fetchField();

      // Save it to the state for future page loads
      \Drupal::state->set('my_value', $value);
    }
  }

  // Return the value
  return $value;
}

With the above code, the first time this function is hit, it will first check if the value exists in the static cache (this page load), and when it doesn't, it attempts to retrieve it from the state cache, and when it doesn't it finally generates it with a database query, saving it both to the static cache, as well as the state.

If it hits this function again on the same page load, the value will be in the static cache, so none of the internal code is needed, and the value is returned from the static cache.

On a future page load, the first time this function is hit, nothing is retrieved from the static cache, so it will pull it from the state cache. If the function is hit again on that page load, the value will be in the static cache and returned from that.

3

The major difference is that drupal_static() saves values in a PHP static variable (static $data = array(), in that function). As such, it can be used to store values that are used when serving the same page. (Normally, drupal_static() is used as cache.)

The class returned by \Drupal::state() handles values that need to be preserved between requests. As such, it is probable it stores its values in a database table. (It depends from the exact implementation done from that class.)

drupal_static() is faster since it saves its values in the memory, but using states doesn't make a lot of difference.

As for recommending one, both are recommended. It's up to you using the one that suits your needs. Do you need a cross-request value, or a value you use only in one request?

3

When you want to store hard to compute data in memory you use a static variable. But to store this data in the database the State API is not the right place, despite the similar name:

The State API provides a place for developers to store information about the system's state.

Use instead Drupal::cache().

Store data in cache:

\Drupal::cache('data')->set($cid, $data, Cache::PERMANENT, ['heavy:' . $heavy_id]);

$cid is a unique cache key, which is used to retrieve the data from cache:

$data = \Drupal::cache('data')->get($cid);

Set a cache tag as fourth parameter so that you can invalidate the cache entry if it becomes outdated:

\Drupal\Core\Cache\Cache::invalidateTags(['heavy:1']);

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.