function VariationCache::getMultiple

Gets multiple cache entries based on a set of cache keys.

Parameters

array $items: An associative array keyed by arbitrary identifiers. Each value is a set of arguments you would otherwise pass to ::get(). Example:

$items = [
  'item_a' => [
    [
      'key1',
      'key2',
    ],
    $cacheability_a,
  ],
  'item_b' => [
    [
      'another_key',
    ],
    $cacheability_b,
  ],
];

Return value

array An associative array keyed by the same keys as $items, containing only the items found in the cache. Items that did not resolve are omitted.

Overrides VariationCacheInterface::getMultiple

File

core/lib/Drupal/Core/Cache/VariationCache.php, line 61

Class

VariationCache
Wraps a regular cache backend to make it support cache contexts.

Namespace

Drupal\Core\Cache

Code

public function getMultiple(array $items) : array {
  // This method does not use ::getRedirectChain() like ::get() does, because
  // we are looking for multiple cache entries and can therefore optimize the
  // following of redirect chains by calling ::getMultiple() on the underlying
  // cache backend.
  //
  // However, ::getRedirectChain() has an internal cache that we could both
  // benefit from and contribute to whenever we call this function. So any use
  // or manipulation of $this->redirectChainCache below is for optimization
  // purposes. A description of the internal cache structure is on the
  // property documentation of $this->redirectChainCache.
  //
  // Create a map of CIDs with their associated $items index and cache keys.
  $cid_map = [];
  foreach ($items as $index => [$keys, $cacheability]) {
    // Try to optimize based on the cached redirect chain.
    if ($chain = $this->getValidatedCachedRedirectChain($keys, $cacheability)) {
      $last_item = end($chain);
      // Immediately skip processing the CID for cache misses.
      if ($last_item === FALSE) {
        continue;
      }
      // We do not need to calculate the initial CID as its part of the chain.
      $initial_cid = array_key_first($chain);
      // Prime the CID map with the last known redirect for the initial CID.
      assert($last_item->data instanceof CacheRedirect);
      $cid = $this->createCacheIdFast($keys, $last_item->data);
    }
    else {
      $cid = $initial_cid = $this->createCacheIdFast($keys, $cacheability);
    }
    $cid_map[$cid] = [
      'index' => $index,
      'keys' => $keys,
      'initial' => $initial_cid,
    ];
  }
  // Go over all CIDs and update the map according to found redirects. If the
  // map is empty, it means we've followed all CIDs to their final result or
  // lack thereof.
  $results = [];
  while (!empty($cid_map)) {
    $new_cid_map = [];
    $fetch_cids = array_keys($cid_map);
    foreach ($this->cacheBackend
      ->getMultiple($fetch_cids) as $cid => $result) {
      $info = $cid_map[$cid];
      // Add redirects to the next CID map, so the next iteration can look
      // them all up in one ::getMultiple() call to the cache backend.
      if ($result->data instanceof CacheRedirect) {
        $redirect_cid = $this->createCacheIdFast($info['keys'], $result->data);
        $new_cid_map[$redirect_cid] = $info;
        $this->redirectChainCache[$info['initial']][$cid] = $result;
        continue;
      }
      $results[$info['index']] = $result;
    }
    // Any CID that did not get a cache hit is still in $fetch_cids. Add them
    // to the internal redirect chain cache as a miss.
    foreach ($fetch_cids as $fetch_cid) {
      $info = $cid_map[$fetch_cid];
      $this->redirectChainCache[$info['initial']][$fetch_cid] = FALSE;
    }
    $cid_map = $new_cid_map;
  }
  return $results;
}

Buggy or inaccurate documentation? Please file an issue. Need support? Need help programming? Connect with the Drupal community.