【问题标题】:Facebook Graph API caching JSON responseFacebook Graph API 缓存 JSON 响应
【发布时间】:2015-08-21 22:02:31
【问题描述】:

我正在使用 Facebook Graph API 从 Facebook 粉丝页面获取内容,然后将它们显示到网站中。我正在这样做,它正在工作,但不知何故,我的托管服务提供商似乎每隔一段时间就限制我的请求......所以我想缓存响应,并且每 8 小时只请求一个新请求例子。

$data = get_data("https://graph.facebook.com/12345678/posts?access_token=1111112222233333&limit=20&fields=full_picture,link,message,likes,comments&date_format=U");
$result = json_decode($data);

get_data 函数使用 CURL 的方式如下:

function get_data($url) {
    $ch = curl_init();
    $timeout = 5;
    curl_setopt($ch, CURLOPT_URL, $url);
    curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
    curl_setopt($ch, CURLOPT_CONNECTTIMEOUT, $timeout);
    curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, false);
    $datos = curl_exec($ch);
    curl_close($ch);
    return $datos;
}

这很好用,我可以输出 JSON 数据响应并在我的网站中随意使用它来显示内容。但是正如我所提到的,在我的托管中,这似乎每次 X 次都会失败,我想是因为我受到了限制。我试图使用我在 Stackoverflow 看到的一些代码来缓存响应。但我无法弄清楚如何集成和使用这两个代码。我已经设法创建了缓存文件,但我无法从缓存文件中正确读取并避免向 Facebook 图形 API 发出新请求。

// cache files are created like cache/abcdef123456...
    $cacheFile = 'cache' . DIRECTORY_SEPARATOR . md5($url);

    if (file_exists($cacheFile)) {
        $fh = fopen($cacheFile, 'r');
        $cacheTime = trim(fgets($fh));

        // if data was cached recently, return cached data
        if ($cacheTime > strtotime('-60 minutes')) {
            return fread($fh);
        }

        // else delete cache file
        fclose($fh);
        unlink($cacheFile);
    }

$fh = fopen($cacheFile, 'w');
    fwrite($fh, time() . "\n");
    fwrite($fh, $json);
    fclose($fh);

return $json;

非常感谢您的帮助!

【问题讨论】:

  • 过早的优化是万恶之源。您是否有证据表明您的托管服务提供商正在限制您的出站连接(您是否使用共享托管?)?只是问可能更容易? Facebook 也可能会限制您的请求,但在这种情况下,他们会在回复中表明这一点。是否每隔 x 次,$result 的值就会发生变化,并且您的代码无法处理它,因为它缺少您期望的属性?
  • 我建议像 Mohammed Asif 所建议的那样使用 memcache(d),这是一种管理这些事情的好方法。
  • @PhpMyCoder 不,我不确定,但它总是在本地主机上运行,​​而不是在我的免费托管中,所以我很确定它们是限制的。此外,facebook 响应没有给出任何错误。我只是得到了诸如超出最大时间请求之类的东西...当时,我尝试在本地主机上,完全没有问题:)
  • @qalbiol 听起来您的问题是您正在使用免费托管(可能与许多其他网站共享 IP)。如果他们中的任何一个也向 Facebook 的 API 发出请求,我想你们都会一起受到速率限制(FB 可能会根据 IP 限制进行)。

标签: javascript php json facebook-graph-api caching


【解决方案1】:

如果您的托管服务提供商通过代理服务器推送您的所有出站请求 - 您可以尝试通过在请求开头附近添加一个额外参数来阻止它:

https://graph.facebook.com/12345678/posts?p=(randomstring)&access_token=1111112222233333&limit=20&fields=full_picture,link,message,likes,comments&date_format=U

我已成功地将其用于对第三方数据提供商的出站呼叫。当然我不知道你的具体问题是不是这个问题。如果他们拒绝带有他们不期望的参数的请求,您也可能会被提供商咬伤。

【讨论】:

    【解决方案2】:

    此答案将为您的项目添加更多依赖项,但它可能比滚动您自己的东西更值得。

    您可以使用Guzzle HTTP 客户端和HTTP Cache 插件。

    $client = new Client('http://www.test.com/');
    
    $cachePlugin = new CachePlugin(array(
        'storage' => new DefaultCacheStorage(
            new DoctrineCacheAdapter(
                new FilesystemCache('/path/to/cache/files')
            )
        )
    ));
    
    $client->addSubscriber($cachePlugin);
    
    $request = $client->get('https://graph.facebook.com/12345678/posts?access_token=1111112222233333&limit=20&fields=full_picture,link,message,likes,comments&date_format=U');
    $request->getParams()->set('cache.override_ttl', 3600*8); // 8hrs
    
    $data = $request->send()->getBody();
    $result = json_decode($data);
    

    【讨论】:

      【解决方案3】:

      不确定是否可以使用 memcache,如果可以的话:

      $cacheFile = 'cache' . DIRECTORY_SEPARATOR . md5($url);
      $mem = new Memcached();
      $mem->addServer("127.0.0.1", 11211);
      $cached = $mem->get($cacheFile);
      if($cached){
        return $cached;
      }
      else{
        $data = get_data($url);
        $mem->set($cacheFile, json_encode($data), time() + 60*10); //10 min
      }
      

      【讨论】:

        【解决方案4】:

        在尝试构建缓存和缓存实际对象(甚至数组)时,有些想法可能会派上用场。

        函数 serializeunserialize 允许您获取对象或数组的字符串表示形式,因此您可以将其缓存为纯文本,然后像以前一样从字符串中弹出对象/数组。

        filectime 允许您获取文件的最后修改日期,因此在创建文件时,您可以依赖此信息来查看缓存是否已过时,就像您尝试实现它一样。

        对于整个工作代码,你去吧:

        function get_data($url) {
            /** @var $cache_file is path/to/the/cache/file/based/on/md5/url */
            $cache_file = 'cache' . DIRECTORY_SEPARATOR . md5($url);
            if(file_exists($cache_file)){
                /** 
                 * Using the last modification date of the cache file to check its validity 
                 */
                if(filectime($cache_file) < strtotime('-60 minutes')){
                    unlink($cache_file);
                } else {
                    echo 'TRACE -- REMOVE ME -- out of cache';
                    /** 
                     * unserializing the object on the cache file 
                     * so it gets is original "shape" : object, array, ...  
                     */
                    return unserialize(file_get_contents($cache_file));
                }
            }
        
            $ch = curl_init();
            $timeout = 5;
            curl_setopt($ch, CURLOPT_URL, $url);
            curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
            curl_setopt($ch, CURLOPT_CONNECTTIMEOUT, $timeout);
            curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, false);
            $data = curl_exec($ch);
            curl_close($ch);
        
            /** 
             * We actually did the curl call so we need to (re)create the cache file 
             * with the string representation of our curl return we got from serialize 
             */
            file_put_contents($cache_file, serialize($data));
        
            return $data;
        }
        

        PS:请注意,我将实际函数 get_data 上的 $datos 变量更改为更常见的 $data

        【讨论】:

        • 感谢@b.enoit.be,我能够让它工作,并且我的托管服务提供商不再遇到任何问题。问候,E.
        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 2013-05-29
        • 2023-01-29
        • 1970-01-01
        • 2019-07-29
        • 2011-10-09
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多