如何存储来自JSON api的大部分静态数据?

时间:2012-12-08 02:53:11

标签: php database json api

我的php项目正在使用reddit JSON api来获取当前页面提交的标题。

现在我每次加载页面时都会运行一些代码,而且我遇到了一些问题,即使没有真正的API限制。

我想以某种方式在本地存储提交的标题。你能推荐最好的方法吗?该网站正在appfog上运行。你会推荐什么?

这是我目前的代码:

<?php

/* settings */

$url="http://".$_SERVER['HTTP_HOST'].$_SERVER['REQUEST_URI'];

$reddit_url = 'http://www.reddit.com/api/info.{format}?url='.$url;

$format = 'json'; //use XML if you'd like...JSON FTW!
$title = '';

/* action */
$content = get_url(str_replace('{format}',$format,$reddit_url)); //again, can be xml or json
if($content) {
    if($format == 'json') {
        $json = json_decode($content,true);
        foreach($json['data']['children'] as $child) { // we want all children for this example
            $title= $child['data']['title'];
        }
    }
}

/* output */


/* utility function:  go get it! */
function get_url($url) {
    $ch = curl_init();
    curl_setopt($ch,CURLOPT_URL,$url);
    curl_setopt($ch,CURLOPT_RETURNTRANSFER,1);
    curl_setopt($ch,CURLOPT_CONNECTTIMEOUT,1);
    $content = curl_exec($ch);
    curl_close($ch);
    return $content;
}
?>

谢谢!

4 个答案:

答案 0 :(得分:4)

简介

以下是代码的修改版本

$url = "http://stackoverflow.com/";
$loader = new Loader();
$loader->parse($url);
printf("<h4>New List : %d</h4>", count($loader));
printf("<ul>");
foreach ( $loader as $content ) {
    printf("<li>%s</li>", $content['title']);
}
printf("</ul>");

输出

新名单:7

  • 来自Joel Spolsky和Jeff Atwood的新播客。
  • 良好的网站,例如代码/ Pyhton
  • stackoverflow.com显然是互联网历史上最好的网络代码,reddit应该更好地开始复制它。
  • 使用网站为程序员提供类似reddit的OpenID
  • 优秀的开发者网站。
  • Stack Overflow公开发布
  • Stack Overflow,一个编程Q&amp;网站。 &安培; Reddit可以从他们的界面中学到很多东西!

Simple Demo

问题

我在这里看到了你想要实现的一些事情,即

  • 我想以某种方式存储本地提交的标题
  • 现在我正在每次加载页面时运行一些代码

根据我的理解,您需要的是一个简单的数据缓存副本,这样您就不必一直加载该网址。

简单解决方案

您可以使用的简单缓存系统是memcache ..

示例A

$url = "http://stackoverflow.com/";

// Start cache
$m = new Memcache();
$m->addserver("localhost");
$cache = $m->get(sha1($url));

if ($cache) {
    // Use cache copy
    $loader = $cache;
    printf("<h2>Cache List: %d</h2>", count($loader));
} else {

    // Start a new Loader
    $loader = new Loader();
    $loader->parse($url);
    printf("<h2>New List : %d</h2>", count($loader));
    $m->set(sha1($url), $loader);
}

// Oupput all listing
printf("<ul>");
foreach ( $loader as $content ) {
    printf("<li>%s</li>", $content['title']);
}
printf("</ul>");

示例B

您可以使用Last Modification Date作为缓存键,这样您只能在修改文档时保存新副本

$headers = get_headers(sprintf("http://www.reddit.com/api/info.json?url=%s",$url), true);
$time = strtotime($headers['Date']); // get last modification date 
$cache = $m->get($time);

if ($cache) {
    $loader = $cache;
}

由于您的类实现了JsonSerializable,您可以对结果进行json编码,并将其存储在MongoDB或MySQL等数据库中

 $data = json_encode($loader);
 // Save to DB 

使用的课程

class Loader implements IteratorAggregate, Countable, JsonSerializable {
    private $request = "http://www.reddit.com/api/info.json?url=%s";
    private $data = array();
    private $total;

    function parse($url) {
        $content = json_decode($this->getContent(sprintf($this->request, $url)), true);
        $this->data = array_map(function ($v) {
            return $v['data'];
        }, $content['data']['children']);
        $this->total = count($this->data);
    }

    public function getIterator() {
        return new ArrayIterator($this->data);
    }

    public function count() {
        return $this->total;
    }

    public function getType() {
        return $this->type;
    }

    public function jsonSerialize() {
        return $this->data;
    }


    function getContent($url) {
        $ch = curl_init();
        curl_setopt($ch, CURLOPT_URL, $url);
        curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
        curl_setopt($ch, CURLOPT_CONNECTTIMEOUT, 1);
        $content = curl_exec($ch);
        curl_close($ch);
        return $content;
    }
}

答案 1 :(得分:0)

我不确定你的问题是什么,但弹出的第一件事是:

foreach($json['data']['children'] as $child) { // we want all children for this example
    $title= $child['data']['title'];
}

您确定要覆盖$title吗?实际上,这只会保留最后一个$child标题。

现在,问你的问题。我假设您正在寻找某种机制来缓存请求的URL的内容,因此您不必每次都重新发出请求,对吗?我对appFog没有任何经验,只有orchestra.io,但我相信他们对写入文件有相同的限制,因为你只能写入临时文件。

我的建议是将(处理过的)响应缓存在:

  • APC与短TTL共享内存
  • 临时文件
  • 数据库

您可以使用URL +参数的哈希值作为查找键,在get_url()内执行此检查意味着您不需要更改代码的任何其他部分,它只需要~3 LOC

答案 2 :(得分:0)

之后:

if($format == 'json') {
    $json = json_decode($content,true);
    foreach($json['data']['children'] as $child) { // we want all children for this example
        $title = $child['data']['title'];
    }
}

}`

然后存储在json文件中并将其转储到本地文件夹网站路径

$storeTitle = array('title'=>$title)

$fp = fopen('../pathToJsonFile/title.json'), 'w');
fwrite($fp, json_encode($storeTitle));
fclose($fp);

然后您可以随时调用json文件并对其进行解码并将标题提取到变量中以供使用

答案 3 :(得分:0)

我通常只是将数据存储为平面文件,如下所示:

<?php
define('TEMP_DIR', 'temp/');
define('TEMP_AGE', 3600);

function getinfo($url) {
    $temp = TEMP_DIR . urlencode($url) . '.json';

    if(!file_exists($temp) OR time() - filemtime($temp) > TEMP_AGE) {
        $info = "http://www.reddit.com/api/info.json?url=$url";
        $json = file_get_contents($info);
        file_put_contents($temp, $json);
        }
    else {
        $json = file_get_contents($temp);
        }

    $json = json_decode($json, true);
    $titles = array();
    foreach($json['data']['children'] as $child) {
        $titles[] = $child['data']['title'];
        }
    return $titles;
    }

$test = getinfo('http://imgur.com/');
print_r($test);

PS。 我使用file_get_contents来获取json数据,您可能有自己的理由使用curl。 我也不检查格式,显然你更喜欢json。