如何在php中为json api实现缓存系统
Posted
技术标签:
【中文标题】如何在php中为json api实现缓存系统【英文标题】:How to implement cache system in php for json api 【发布时间】:2013-10-04 18:14:33 【问题描述】:我的网站上有一些自定义社交按钮,我使用 API 中的 json 为其获取分享号/关注者号。 我试图实现一个缓存系统来减少加载时间并消除因过度使用 API 而被“警告”的风险。但是,我在这方面没有成功,主要是因为我不太了解集成步骤。 我希望有人可以帮我集成一个缓存系统。
以下是 Twitter、Google Plus 和 Instagram 的 php 代码:
推特 ob_start(); $twittershare = 'http://cdn.api.twitter.com/1/urls/count.json?url='.$product["href"] .''; $ch = curl_init(); curl_setopt($ch, CURLOPT_URL, $twittershare); curl_setopt($ch, CURLOPT_HEADER, 0); $jsonstring = curl_exec($ch); curl_close($ch); $bufferstr = ob_get_contents(); ob_end_clean(); $json = json_decode($bufferstr); 回声$json->计数; 谷歌加号 $url = ''.$product["href"] .''; $ch = curl_init(); curl_setopt($ch, CURLOPT_URL, "https://clients6.google.com/rpc?key=xxxxxxxxxx"); curl_setopt($ch, CURLOPT_POST, 1); curl_setopt($ch, CURLOPT_POSTFIELDS, '["method":"pos.plusones.get","id":"p","params":"nolog":true,"id":"' . $url '","source":"widget","userId":"@viewer","groupId":"@self","jsonrpc":"2.0","key":"p","apiVersion" :"v1"]'); curl_setopt($ch, CURLOPT_RETURNTRANSFER, true); curl_setopt($ch, CURLOPT_HTTPHEADER, array('Content-type: application/json')); curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, false); $curl_results = curl_exec($ch); curl_close($ch); $json = json_decode($curl_results, true); $count = intval($json[0]['result']['metadata']['globalCounts']['count']); $数据 = 数组(); $data['plus_count'] = (string) $count; $data['url'] = $url; 回声 $data['plus_count']; Instagram(获取关注者编号) ob_start(); $insta = 'https://api.instagram.com/v1/users/00000000?access_token=token'; $ch = curl_init(); curl_setopt($ch, CURLOPT_URL, $insta); curl_setopt($ch, CURLOPT_HEADER, 0); $jsonstring = curl_exec($ch); curl_close($ch); $bufferstr = ob_get_contents(); ob_end_clean(); $json = json_decode($bufferstr); echo $json->data->counts->followed_by;希望大家可以一步步指导我如何为上面的代码sn-ps实现缓存系统。
【问题讨论】:
您提到“消除因过度使用 API 而被‘警告’的风险”,我问自己:这些限制是什么?您的网站收到这么多请求吗?至于缓存系统:这取决于:您可以将请求的结果存储在数据库中或带有时间戳的 memcached 中,并且仅根据需要更新它们(通过不同的服务,例如通过 cron 作业)。您的页面只是从数据后端读取并在它不可用时获取它。 @nietonfir 老实说,我不知道限制,但主要问题是页面加载时间长。是的,我读过它,我只是不知道如何实际实现它。数据库将结果存储在服务器上的文件中不是更容易且压力更小吗?同样,我只是根据我在这里和那里读到的内容进行猜测。 不,您不想在文件中存储任何内容。如果页面加载时间是您主要关心的问题,那么不要在请求期间从 API(或您的缓存系统)获取数据,而是异步(通过 AJAX)获取数据。这也将允许您独立实现缓存系统。 【参考方案1】:好吧,正如我在评论中提到的,我会使用 Memcached 和一个数据库,但我会起草一个仅数据库的解决方案(使用 PDO 用于 twitter)并将 Memcached 部分作为奖励练习留给你。 ;) 我会通过 AJAX 加载关注者信息,以减少页面加载时间,例如关注者数量需要更新。
我将使用以下数据库架构:
CREATE TABLE IF NOT EXISTS `Followers` (
`id` int(11) NOT NULL AUTO_INCREMENT,
`url` varchar(100) NOT NULL,
`data` longtext NOT NULL,
`followers` int(5) NOT NULL,
`last_update` TIMESTAMP DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
PRIMARY KEY (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8;
首先我要定义一个接口,这样你就不用依赖任何实现了:
interface SocialFollowers
public function getFollowers();
然后,对于 twitter 共享 API,我将有一个实现类,它获取数据库句柄和用于初始化的目标 URL。类属性由检索到的数据(如果可用)填充。如果时间戳足够新,您将立即获得关注者数量,否则会查询 API、存储结果并检索关注者数量。
class TwitterFollowers implements SocialFollowers
private $data = null;
private $url = "";
private $db = null;
private $followers = null;
protected $shareURL = "https://cdn.api.twitter.com/1/urls/count.json?url=";
public function __construct($db, $url)
// initialize the database connection here
// or use an existing handle
$this->db = $db;
// store the url
$this->url = $url;
// fetch the record from the database
$stmt = $this->db->prepare('SELECT * FROM `Followers` WHERE url = :url ORDER BY last_update DESC LIMIT 1');
$stmt->bindParam(":url", $url);
$stmt->execute();
$this->data = $stmt->fetch(PDO::FETCH_ASSOC);
if (!empty($this->data))
$this->followers = $this->data["followers"];
public function getFollowers()
// create a timestamp that's 30 minutes ago
// if it's newer than the value from the database -> call the api
$old = new DateTime();
$old->sub(new DateInterval("PT30M"));
if (is_null($this->followers) || (new DateTime($this->data["last_update"]) < $old) )
return $this->retrieveFromAPI();
return $this->followers;
private function retrieveFromAPI()
// mostly untouched
ob_start();
$twittershare = $this->shareURL . $this->url;
$ch = curl_init();
curl_setopt($ch, CURLOPT_URL, $twittershare);
curl_setopt($ch, CURLOPT_HEADER, 0);
$jsonstring = curl_exec($ch);
curl_close($ch);
$bufferstr = ob_get_contents();
ob_end_clean();
$json = json_decode($bufferstr);
$this->followers = $json->count;
// store the retrieved values in the database
$stmt = $this->db->prepare('INSERT INTO Followers (url, data, followers)'
.'VALUES (:url, :data, :followers)');
$stmt->execute(array(
":url" => $this->url,
":data" => $bufferstr,
":followers" => $this->followers
));
return $this->followers;
对于 Facebook、Google+、the-next-social-network,您只需添加另一个实现。
请注意,此代码未经测试。它错过了 PDO 查询的一些 try/catch 块,并且还有改进的空间(例如:缺少某种锁定机制来防止同时检索相同的 URL,是否有必要存储返回的 blob 等)。
希望对你有所帮助。
[编辑] 我稍微更新了代码(修复了一些拼写错误和转换问题)并对其进行了测试。您可以在github 找到工作版本。所缺少的只是像 ajax sn-p(假设是 jQuery)这样的
$.ajax(
url: "http://example.com/twitter.php",
type: "get",
data: url: "http://***.com"
success: function(data, textStatus, jqXHR)
// Update the corresponding counter like
// $("#twitterfollowers").text(data);
console.log(data);
);
【讨论】:
感谢@nietonfir 的回答,但不幸的是它不起作用,它破坏了页面。我不知道,我只是不喜欢乱搞数据库,它是存储我网站重要信息的主要核心。 @CristiSilaghi 我不知道您是如何得出“搞乱数据库”的结论,因为数据库是用于存储数据的。 ;-) 如果您不想将该信息保存在与您的网站相同的存储层中,只需使用另一个数据库/表。正如我所说,代码没有经过测试或完成(例如缺少 AJAX 调用),但应该给你一个想法。 你说得对,我没有考虑过使用单独的数据库。我真傻:) 我不知道这种 php 编码(在这个高级别),所以不完整的代码并不能真正帮助我。这就是为什么我发布这个问题,以获得实施方面的帮助。我在网上找了几个教程,但我是缓存部分的php新手。 @CristiSilaghi 我更新了答案并修复了代码示例。我希望工作代码为您提供足够的信息来帮助您继续前进。祝你好运。 @MaXi32 你可以,但这首先会破坏缓存的整个概念,因为会话绑定到具有相应会话密钥的用户代理。并且会话处理程序默认是文件,所以数据库连接/redis/memcached/...肯定会更快。以上是关于如何在php中为json api实现缓存系统的主要内容,如果未能解决你的问题,请参考以下文章