使用json_encode临时存储来自YouTube Data API的资源

时间:2016-10-17 21:55:02

标签: php json youtube

我一直在制作一个自定义WordPress插件,用于将YouTube内容集成到游戏博客中,为了限制每日API配额的压力,我一直试图想出一种存储临时缓存的方法物品在24小时后过期。

我创建了以下类来管理数据:

public class YouTubeDataCache {
    protected $dataObject;
    protected $expirationDate;

    __construct($dataObject) {
        $this->dataObject = $dataObject;
        $this->expirationDate = time() + 86400;
    }

    public function isExpired() {
        return $this->expirationDate < time();
    }

    public function getDataObject() {
        return $this->dataObject;
    }
}

然后,我在这个类的实例上调用json_encode($dataCache)来生成我可以存储在数据库中的实例的JSON表示。

但是,一旦我开始测试,我发现了两个重要的问题:

  1. 尽管验证了Google的API返回了实际结果,但数据库条目仍为空白。
  2. 当我尝试在解码对象上调用json_decode()时,对数据库中拉出 out 的字符串调用isExpired()会返回未定义方法的致命错误。
  3. 我的问题是双重的:

    1. 如何确保将所有必需的数据元素编码到JSON字符串中?
    2. 如何在调用json_decode()
    3. 后保留对对象方法的访问权限

1 个答案:

答案 0 :(得分:0)

花了一些时间来追踪这一点,但这是我提出的解决方案。

如何将所有必要的数据元素存储在缓存中?

具体情况会因个别用例而略有不同,但其要点是:json_encode()只会编码公开变量。

由于我的$dataObject$expirationDate被定义为protectedjson_encode()无权访问这些值,因此无法编码空白对象。糟糕。

深入挖掘,从YouTube API返回的对象还包含大量protected数据元素,因此即使我将类变量更改为public,我仍会遇到类似的试图存储视频缩略图等问题。

最终,我必须创建自己的序列化功能。

较新版本的PHP可以使用JsonSerializable接口并定义特定于类的实现,根据文档,“返回可以通过json_encode()序列化的数据”

由于我无法准确预测此插件的PHP用户版本将会运行,我选择仅创建toJSON()方法,并修改构造函数以从{{中提取特定数据元素1}}。

首先,构造函数/类变量:

对于我的特定用例,我只关心ID,代码段,状态和缩略图信息。如果您需要其他数据元素,您需要深入了解响应对象的结构,以查看序列化函数需要手动包含的内容。

$dataObject

注意:这里有一点需要注意。从技术上讲,缩略图信息包含在代码段中,但它绑定在YouTubeDataCache { protected $objectId; protected $snippet; protected $status; protected $thumbnails = array(); protected $expirationDate; __construct($dataObject = null) { $this->expirationDate = time() + 86400; if ($dataObject === null) { return; // I'll explain later } $this->objectId = $dataObject->getId(); $this->snippet = $dataObject->getSnippet(); $this->status = $dataObject->getStatus(); $thumbs = $dataObject->getThumbnails(); if ($thumbs->getDefault()) { $this->addThumbnail('default', $thumbs->getDefault()); } if ($thumbs->getMedium()) { $this->addThumbnail('medium', $thumbs->getMedium()); } if ($thumbs->getHigh()) { $this->addThumbnail('high', $thumbs->getHigh()); } if ($thumbs->getMaxRes()) { $this->addThumbnail('maxRes', $thumbs->getMaxRes()); } } public function setExpirationDate($expirationDate) { $this->expirationDate = $expirationDate; } public function addThumbnail($name, $data) { $this->thumbnails[$name] = $data; } public function getObjectId() { return $this->objectId; } public function setObjectId($objectId) { $this->objectId = $objectId; } public function getSnippet() { return $this->snippet; } public function setSnippet($snippet) { $this->snippet = $snippet; } public function getStatus() { return $this->status; } public function setStatus($status) { $this->status = $status; } } 数组中。由于我最终需要将其从该阵列中拉出来,因此在此处进行操作可为接下来的内容提供更一致的访问模式。

接下来我添加了自定义序列化方法

注意:这是一种类方法。我只是把它拉出来以便于阅读

protected

使用此函数,我现在可以调用public function toJSON() { $array = array( 'objectId' => $this->objectId, 'snippet' => $this->snippet, 'status' => $this->status, 'thumbnails' => $this->thumbnails, 'expirationDate' => $this->expirationDate ); return json_encode($array); } 来生成数据的准确编码JSON表示,然后我可以将其写入数据库,这将我们带到解决方案的第二部分。

如何保留对缓存对象方法的访问权限?

结果$cacheObject->toJson()创建了json_decode实例或关联数组(取决于您选择如何调用该函数)。在任何一种情况下,它都没有最初用于创建JSON字符串的类中的任何方法,因此我最终还必须创建自定义反序列化方法。

我选择创建此特定函数stdClass,以便我不需要缓存对象的实例来使用它。

static

最终的类定义

仅供参考,以下是最终的课程定义:

public static function fromJSON($json) {
    $data = json_decode($json);

    $cacheObject = new YouTubeDataCache();
    /* This is why the constructor now accepts a null argument.
    I won't always have access to an API response object from
    Google, and in such cases, it's faster to just call setters
    on this class rather than jumping through hoops to create the
    Google class instance. */

    $cacheObject->setExpirationDate($data->expirationDate);
    $cacheObject->setObjectId($data->objectId);
    $cacheObject->setSnippet($data->snippet);
    $cacheObject->setStatus($data->status);

    foreach($data->thumbnails as $name => $thumbnail) {
        $cacheObject->addThumbnail($name, $thumbnail);
    }

    return $cacheObject;
}