6

私のウェブサイトには、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);

    echo $json->count;

  • グーグルプラス
    $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 = 配列();
    $data['plus_count'] = (文字列) $count;
    $data['url'] = $url;
    echo $data['plus_count'];

  • Instagram (フォロワー数の取得)
    ob_start();
    $insta = 'https://api.instagram.com/v1/users/00000000?access_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;

上記のコード スニペットのキャッシュ システムを実装する方法について、順を追って説明していただければ幸いです。

4

1 に答える 1

5

私のコメントで述べたように、私はMemcachedとデータベースを使用しますが、データベースのみのソリューション (Twitter 用の PDO を使用) を作成し、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+、次のソーシャル ネットワークの場合は、別の実装を追加するだけです。

このコードはテストされていないことに注意してください。PDO クエリのいくつかの try/catch ブロックが欠落しており、改善の余地があります (例: 同じ URL の同時取得を防ぐためのある種のロック メカニズムが欠落している、返された BLOB を格納する必要があるなど)。

これがお役に立てば幸いです。

[編集] コードを少し更新し (いくつかのタイプミスと変換の問題を修正)、テストしました。動作するバージョンはgithubにあります。不足しているのは、次のような ajax スニペット (jQuery を想定) だけです

$.ajax({
    url: "http://example.com/twitter.php",
    type: "get",
    data: {url: "http://stackoverflow.com"}
    success: function(data, textStatus, jqXHR) {
        // Update the corresponding counter like
        // $("#twitterfollowers").text(data);
        console.log(data);
    }
});
于 2013-09-29T22:33:32.273 に答える