如何在Silverstripe控制器中缓存JSON响应?

问题描述 投票:0回答:1

[我们有一个Silverstripe 4项目,它充当无头CMS,返回一组格式为JSON的复杂数据模型。

下面是代码示例:

class APIController extends ContentController
{

    public function index(HTTPRequest $request)
    {
        $dataArray['model1'] = AccessPointController::getModel1();
        $dataArray['model2'] = AccessPointController::getModel2();
        $dataArray['model3'] = AccessPointController::getModel3();
        $dataArray['model4'] = AccessPointController::getModel4();
        $dataArray['model5'] = AccessPointController::getModel5();
        $dataArray['model6'] = AccessPointController::getModel6();

        $this->response->addHeader('Content-Type', 'application/json');
        $this->response->addHeader('Access-Control-Allow-Origin', '*');

        return json_encode($dataArray);
    }

我们面临的问题是,数据模型变得如此复杂,JSON的生成时间几乎达到了几秒钟。

仅当网站内容已更新时,JSON才应更改,因此,理想情况下,我们希望缓存JSON,而不是为每个调用动态生成JSON。

在上述示例中,缓存JSON的最佳方法是什么?

silverstripe silverstripe-4
1个回答
0
投票

您看过the silverstripe docs about caching吗?它们确实提供了一种编程方式来将内容存储在缓存中。以及配置选项,哪些后端将用于存储缓存。

一个简单的示例可能是:我在这里延长了缓存的使用时间,但是仍然不应该认为该缓存不是用于存储生成的静态内容,而是为了减少负载。您的应用程序仍然必须每86400秒(24小时)计算一次api响应。

# app/_config/apiCache.yml
---
Name: apicacheconfig
---
# [... rest of your config config ...]
SilverStripe\Core\Injector\Injector:
  Psr\SimpleCache\CacheInterface.apiResponseCache:
    factory: SilverStripe\Core\Cache\CacheFactory
    constructor:
      namespace: "apiResponseCache"
      defaultLifetime: 86400
<?php // app/src/FooController.php

class FooController extends \SilverStripe\Control\Controller {
    public function getCache() {
        return Injector::inst()->get('Psr\SimpleCache\CacheInterface.apiResponseCache');
        // or your own cache (see below):
        // return new MyCache();
    }

    protected function hasDataBeenChanged() {
        // alternative to this method, you could also simply include Page::get()->max('LastEdited') or whatever in your cache key inside index(), but if you are using your own cache system, you need to handle deleting of old unused cache files. If you are using SilverStripe's cache, it will do that for you
        $c = $this->getCache();
        $lastCacheTime = $c->has('cacheTime') ? (int)$c->get('cacheTime') : 0;
        $lastDataChangeTime = strtotime(Page::get()->max('LastEdited'));
        return $lastDataChangeTime > $lastCacheTime;
    }

    public function index() {
        $c = $this->getCache();
        $cacheKey = 'indexActionResponse';
        if ($c->has($cacheKey) && !$this->hasDataBeenChanged()) {
            $data = $c->get($cacheKey);
        } else {
            $dataArray['model1'] = AccessPointController::getModel1();
            $dataArray['model2'] = AccessPointController::getModel2();
            $dataArray['model3'] = AccessPointController::getModel3();
            $dataArray['model4'] = AccessPointController::getModel4();
            $dataArray['model5'] = AccessPointController::getModel5();
            $dataArray['model6'] = AccessPointController::getModel6();
            $data = json_encode($dataArray);
            $c->set($cacheKey, $data);
            $c->set('cacheTime', time());
        }

        $this->response->addHeader('Content-Type', 'application/json');
        $this->response->addHeader('Access-Control-Allow-Origin', '*');

        return json_encode($dataArray);
    }
}

如果您正在寻找一个永久性/持久性缓存,它只会在数据更改时才会更新,我建议您寻找一个不同的后端,或者自己实现一个简单的缓存,并使用它代替Silverstripe缓存。

class MyCache {
    protected function fileName($key) {
        if (strpos($key, '/') !== false || strpos($key, '\\') !== false) {
            throw new \Exception("Invalid cache key '$key'");
        }
        return BASE_PATH . "/api-cache/$key.json";
    }

    public function get($key) {
        if ($this->has($key)) {
            return file_get_contents($this->fileName($key));
        }
        return null;
    }

    public function set($key, $val) {
        file_put_contents($this->fileName($key), $val);
    }

    public function has($key) {
        $f = $this->fileName($key);
        return @file_exists($f);
    }
© www.soinside.com 2019 - 2024. All rights reserved.