如何在ZF2中进行缓存

Sam*_*Sam 6 caching zend-framework2

我刚刚开始全身心投入缓存.我有一个简单的indexAction()来获取所有给定的数据集.我的方法是:

  • 检查现有密钥'controllername-index-index'
  • if existing:返回密钥的值
  • 如果存在,请执行正常操作并添加密钥

密钥内的值应该是将生成并使用我的数据填充的ViewModel.

这是我到目前为止所做的:

<?php
public function indexAction()
{
    $sl = $this->getServiceLocator();
//  $cache = $sl->get('cache');
//  $key = 'kennzahlen-index-index';
//
//  if ($cache->hasItem($key)) {
//      return $cache->getItem($key);
//  }

    $viewModel = new ViewModel();
    $viewModel->setTemplate('kennzahlen/index/index');
    $entityService = $sl->get('kennzahlen_referenzwert_service');
    $viewModel->setVariable('entities', $entityService->findAll());

//  $cache->setItem($key, $viewModel);

    return $viewModel;
}
Run Code Online (Sandbox Code Playgroud)

缓存部分已注释用于测试目的,但基本上这就是我正在做的事情.缓存配置/服务如下所示:

<?php
'cache' => function () {
    return \Zend\Cache\StorageFactory::factory(array(
        'adapter' => array(
            'name' => 'filesystem',
            'options' => array(
                'cache_dir' => __DIR__ . '/../../data/cache',
                'ttl' => 100
            ),
        ),
        'plugins' => array(
            array(
                'name' => 'serializer',
                'options' => array(

                )
            )
        )
    ));
},
Run Code Online (Sandbox Code Playgroud)

序列化和缓存工作得很好,但我对结果缺失感到惊讶.根据ZendDevelopersToolbar告诉我的内容,没有缓存的时间介于1.8s到2.5s之间.取消注释(启用)缓存部分并不能真正改善页面的加载时间.

所以我的问题是:这种方法完全错了吗?是否有不同的,更快速的部件,可以通过一些巧妙的配置技巧保存?

我觉得页面的2秒加载时间肯定太慢了.对我而言,1是给出大量数据的最大值,但肯定不会超过:S

所有帮助/提示/建议将不胜感激.提前致谢!

Jur*_*man 17

一种选择是缓存页面的完整输出,例如基于路由匹配.您需要在路由和调度之间监听哪条路由已匹配,然后采取相应措施:

namespace MyModule;

use Zend\Mvc\MvcEvent;

class Module
{
    public function onBootstrap(MvcEvent $e)
    {
        // A list of routes to be cached
        $routes = array('foo/bar', 'foo/baz');

        $app = $e->getApplication();
        $em  = $app->getEventManager();
        $sm  = $app->getServiceManager();

        $em->attach(MvcEvent::EVENT_ROUTE, function($e) use ($sm) {
            $route = $e->getRouteMatch()->getMatchedRouteName();
            $cache = $sm->get('cache-service');
            $key   = 'route-cache-' . $route;

            if ($cache->hasItem($key)) {
                // Handle response
                $content  = $cache->getItem($key);

                $response = $e->getResponse();
                $response->setContent($content);

                return $response;
            }
        }, -1000); // Low, then routing has happened

        $em->attach(MvcEvent::EVENT_RENDER, function($e) use ($sm, $routes) {
            $route = $e->getRouteMatch()->getMatchedRouteName();
            if (!in_array($route, $routes)) {
                return;
            }

            $response = $e->getResponse();
            $content  = $response->getContent();

            $cache = $sm->get('cache-service');
            $key   = 'route-cache-' . $route;
            $cache->setItem($key, $content);
        }, -1000); // Late, then rendering has happened
    }
}
Run Code Online (Sandbox Code Playgroud)

第二个侦听器检查render事件.如果发生这种情况,将缓存响应的结果.

这个系统(可能没有100%复制/粘贴,但概念)有效,因为如果你Response在路由或调度事件期间返回一个,应用程序将短路应用程序流并停止进一步触发侦听器.然后,它将按原样提供此响应.

请记住,它将是完整的页面(包括布局).如果您不想(仅控制器),请将逻辑移至控制器.第一个事件(现在路线)将发送控制器.尽早收听,因此将省略动作的正常执行.要缓存结果,请检查要侦听的视图层的render事件.

/ update:我写了一个小模块在你的应用程序中使用这个DRY:SlmCache