在PHP中缓存JSON输出

17

我遇到了一个小问题。我一直在与Facebook和Twitter API进行交互,可以轻松地获取状态查询的JSON输出,但是我已经进一步阅读文档,意识到我可能会被限制速率。

我想知道是否有办法每小时缓存一次JSON输出,这样我至少可以尝试防止出现这种情况?如果可以的话,该如何实现?我看了一个YouTube视频,但那并没有提供太多信息,只是告诉我如何将目录清单的内容写入cache.php文件,但它并没有真正指出是否可以用于JSON输出,也没有说明如何使用60分钟的时间间隔,或如何将信息取回缓存文件。

如果有任何帮助或代码,将非常感激,因为教程中似乎很少涉及此类问题。

3个回答

37

这是一个简单的函数,可将缓存添加到获取某些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的重复请求将在下一次从缓存中读取。它将时间戳写入缓存文件的第一行,并且早于一小时的缓存数据会被丢弃。这只是一个简单的示例,您可能需要自定义它。


φàëγö³δΜΘγ†¹:-code $query = "i%20hate%20my%20girlfriend"; $query = urlencode($query); $url = "http://search.twitter.com/search.json?q={$query}&rpp=100&result_type=recent&lang=en"; $tweet = file_get_contents($url); $tweet_array = json_decode($tweet, true);foreach ($tweet_array['results'] as $data) { $profileimg = $data['profile_image_url']; $postfrom = $data['from_user_name']; $postfromid = $data['from_user_id']; $created = $data['created_at']; $message = $data['text']; - GeordieDave1980
我已经在我的代码中留下了一条评论,我不确定如何将其放入评论框中,希望您能够复制粘贴并将其分开,以便您知道它的样子。我对该函数应该怎么做有点困惑。 - GeordieDave1980
在您的情况下,$tweet = file_get_contents($url) 这行代码会给您提供原始的 JSON 数据。这就是您要找的东西。在上述函数中,请使用 $json = file_get_contents($url);。在您的代码中,请使用 $tweet = getJson($url); 来获取并缓存 URL。 - deceze
1
这是一个非常有用的函数。我想知道你是否考虑过使用filemtime()来避免写入每个缓存文件的时间戳?参考:http://php.net/manual/zh/function.filemtime.php - henrywright
@deceze PHP警告:fread()期望精确的2个参数,只提供了1个在getjson.php中。如果我添加return fread($fh,' r '); 错误是:fread()期望参数2是long,但提供了字符串。 - Adrian
显示剩余4条评论

9

为了避免速率限制,使用缓存是一个好主意。以下是一些示例代码,展示了我最近在编写的某些php代码中如何处理Google+数据。

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);
        }

那么getCacheFileName函数在哪里?如果你想使用它,我猜你需要这个函数。 - tvdsluijs

0

我知道这篇帖子已经很老了,但它在Google上显示,因此对于所有寻找的人,我制作了这个简单的程序,它可以curl一个JSON url并将其缓存到一个特定文件夹中的文件中。当再次请求json时,如果5分钟过去了,它将重新curl一次,如果还没有过去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,当调用函数时应该像这样: ccurl('json_url','x') 其中x是id,如果您有问题,请问我 ^_^也请享受(我可能会稍后更新它,以便不使用id的目录)


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接