How to check if result from cache_get() is expired? cache_get always returns an object and I'm a bit confused by its values. There's probably a short generic function that can handle this for once and for all.

$cache = cache_get('key');
if ($cache) { 
  // doesn't work, cache_get always returns an object
}

if (!$cache || ($cache-&gt;created &lt; time() - $cache-&gt;expire)) {
  // cache is expired? I'm not sure
}


Just checking for the data member doesn't cut it.

I had seen the issue reported on d.o (in 2009) but that doesn't really help me fix it on any live site. So I'm looking for a function that will still make cache work for me without resorting to storing the cache myself in the database.
TL;DR Don't, unless you have to. Drupal has long history of optimization and even if it sometimes serves you outdated cache, it's not without a cause. It's to prevent overhead of constant cache wipes. If your application is time-critical for some reasons, read below.



As you can see in the code that does the actual work:

function getMultiple(&amp;$cids) {
  try {
    // Garbage collection necessary when enforcing a minimum cache lifetime.
    $this-&gt;garbageCollection($this-&gt;bin);

    // When serving cached pages, the overhead of using db_select() was found
    // to add around 30% overhead to the request. Since $this-&gt;bin is a
    // variable, this means the call to db_query() here uses a concatenated
    // string. This is highly discouraged under any other circumstances, and
    // is used here only due to the performance overhead we would incur
    // otherwise. When serving an uncached page, the overhead of using
    // db_select() is a much smaller proportion of the request.
    $result = db_query('SELECT cid, data, created, expire, serialized FROM {' . db_escape_table($this-&gt;bin) . '} WHERE cid IN (:cids)', array(':cids' =&gt; $cids));
    $cache = array();
    foreach ($result as $item) {
      $item = $this-&gt;prepareItem($item);
      if ($item) {
        $cache[$item-&gt;cid] = $item;
      }
    }
    $cids = array_diff($cids, array_keys($cache));
    return $cache;
  }
  catch (Exception $e) {
    // If the database is never going to be available, cache requests should
    // return FALSE in order to allow exception handling to occur.
    return array();
  }
}


There is no test built in1, and no limit that makes Core return only unexpired nodes.


The way I prefer if I can, is to delete/hide table rows on database level, for example by creating a proxy view that never returns outdated records in the first place, but usually this is inconvenient. Don't try unless you know what you're doing.
The Drupal-only way would be to add comparison in PHP, like that:

if (isset($cache-&gt;data) and time() &lt; $cache-&gt;expire) {

If your cache is relatively long, you can, and for performance reasons probably should omit testing their expire date on each call and leave it to Drupal's core. It will allow minimum cache lifetime to work with your data, for example. That's how core is doing it.1




1 There are some tests in prepareItem method, but for performance reasons they do not guarantee that outdated cache items will not be returned - see actual code for details.