在PHP中缓存JSON输出


Caching JSON output in PHP

有点小问题。我一直在玩facebook和twitter的API,并获得状态搜索查询的JSON输出,这没问题,但我读了更多,并意识到我最终可能会受到文档中引用的"速率限制"。

我想知道每小时缓存JSON输出是否容易,这样我至少可以尝试防止这种情况发生?如果是这样,是如何做到的?当我尝试一个youtube视频时,它并没有真正给出太多信息——只有如何将目录列表的内容写入cache.php文件,但它并没有指出是否可以使用JSON输出来完成这一点,当然也没有说明如何使用60分钟的时间间隔,或者如何从缓存文件中获取信息。

任何帮助或代码都将不胜感激,因为教程中似乎很少有关于这类事情的内容。

这里有一个简单的函数,它为获取一些URL内容添加了缓存:

function getJson($url) {
    // cache files are created like cache/abcdef123456...
    $cacheFile = 'cache' . DIRECTORY_SEPARATOR . md5($url);
    if (file_exists($cacheFile)) {
        $fh = fopen($cacheFile, 'r');
        $size = filesize($cacheFile);
        $cacheTime = trim(fgets($fh));
        // if data was cached recently, return cached data
        if ($cacheTime > strtotime('-60 minutes')) {
            return fread($fh, $size);
        }
        // else delete cache file
        fclose($fh);
        unlink($cacheFile);
    }
    $json = /* get from Twitter as usual */;
    $fh = fopen($cacheFile, 'w');
    fwrite($fh, time() . "'n");
    fwrite($fh, $json);
    fclose($fh);
    return $json;
}

它使用URL来识别缓存文件,下次将从缓存中读取对相同URL的重复请求。它将时间戳写入缓存文件的第一行,超过一小时的缓存数据将被丢弃。这只是一个简单的例子,您可能需要自定义它。

使用缓存来避免速率限制是个好主意。下面是一些示例代码,展示了我是如何为Google+数据做这件事的,在我最近写的一些php代码中。

private function getCache($key) {
    $cache_life = intval($this->instance['cache_life']); // minutes
    if ($cache_life <= 0) return null;
    // fully-qualified filename
    $fqfname = $this->getCacheFileName($key);
    if (file_exists($fqfname)) {
        if (filemtime($fqfname) > (time() - 60 * $cache_life)) {
            // The cache file is fresh.
            $fresh = file_get_contents($fqfname);
            $results = json_decode($fresh,true);
            return $results;
        }
        else {
            unlink($fqfname);
        }
    }
    return null;
}
private function putCache($key, $results) {
    $json = json_encode($results);
    $fqfname = $this->getCacheFileName($key);
    file_put_contents($fqfname, $json, LOCK_EX);
}

并使用它:

        // $cacheKey is a value that is unique to the
        // concatenation of all params. A string concatenation
        // might work. 
        $results = $this->getCache($cacheKey);
        if (!$results) {
            // cache miss; must call out
            $results = $this->getDataFromService(....);
            $this->putCache($cacheKey, $results);
        }

我知道这篇文章很旧,但它显示在谷歌上,所以对于所有寻找它的人来说,我做了一个简单的帖子,卷曲一个JSON url并将其缓存在特定文件夹中的文件中,当JSON再次被请求时,如果经过了5分钟,它会卷曲它,如果5分钟还没有通过,它会从文件中显示它,它使用时间戳来跟踪时间,是的,享受

function ccurl($url,$id){
    $path    = "./private/cache/$id/";
    $files = scandir($path);
    $files = array_values(array_diff(scandir($path), array('.', '..')));
    if(count($files) > 1){
      foreach($files as $file){
        unlink($path.$file);
        $files = scandir($path);
        $files = array_values(array_diff(scandir($path), array('.', '..')));
      }
    }
    if(empty($files)){
      $c = curl_init();
      curl_setopt($c, CURLOPT_URL, $url);
      curl_setopt($c, CURLOPT_TIMEOUT, 15);
      curl_setopt($c, CURLOPT_RETURNTRANSFER, true);
      curl_setopt($c, CURLOPT_USERAGENT,
          'Mozilla/5.0 (Windows NT 6.2; WOW64; rv:17.0) Gecko/20100101 Firefox/17.0');
      $response = curl_exec($c);
      curl_close ($c);
      $fp = file_put_contents($path.time().'.json', $response);
      return $response;
    }else {

      if(time() - str_replace('.json', '', $files[0]) >  300){
        unlink($path.$files[0]);
        $c = curl_init();
        curl_setopt($c, CURLOPT_URL, $url);
        curl_setopt($c, CURLOPT_TIMEOUT, 15);
        curl_setopt($c, CURLOPT_RETURNTRANSFER, true);
        curl_setopt($c, CURLOPT_USERAGENT,
            'Mozilla/5.0 (Windows NT 6.2; WOW64; rv:17.0) Gecko/20100101 Firefox/17.0');
        $response = curl_exec($c);
        curl_close ($c);
        $fp = file_put_contents($path.time().'.json', $response);
        return $response;
      }else {
        return file_get_contents($path. $files[0]);
      }
    }
  }

对于用法,为所有缓存的文件创建一个目录,对我来说,它的/private/cache,然后在里面为请求缓存创建另一个目录(例如x),当调用函数时,它应该像htisccurl('json_url','x')其中x是id,如果你有问题,请问我^_^也可以享受(我稍后可能会更新它,这样它就不会使用id 的目录