6

全体としてキャッシングに頭を悩ませ始めたところです。指定されたすべてのデータセットを取得する単純な indexAction() があります。私のアプローチは次のとおりです。

  • 既存のキー 'controllername-index-index' を確認します
  • 存在する場合: キーの値を返します
  • 存在しない場合は、通常のアクションを実行してキーを追加します

キー内の値は、生成されてデータが入力される 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;
}

キャッシング部分はテストのためにコメントアウトされていますが、基本的にはこれだけです。キャッシュ構成/サービスは次のようになります。

<?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(

                )
            )
        )
    ));
},

シリアル化とキャッシュは非常にうまく機能しますが、結果が得られないことに驚いています。ZendDevelopersToolbar が教えてくれることによると、キャッシュなしの時間は 1.8 秒から 2.5 秒の範囲です。キャッシュ部分のコメントを解除 (有効) しても、ページの読み込み時間はまったく改善されません。

だから私の質問は: このアプローチは完全に間違っていますか? 巧妙な構成のトリックで保存できる、別のより高速な部分はありますか?

ページの 2 秒の読み込み時間は明らかに遅すぎると感じています。私にとって 1 は、膨大な量のデータを考えると最大値ですが、それ以上のものではないことは確かです :S

すべてのヘルプ/ヒント/提案は大歓迎です。前もって感謝します!

4

1 に答える 1

17

1 つのオプションは、たとえばルートの一致に基づいて、ページの完全な出力をキャッシュすることです。一致として見つかったルーティングとディスパッチの間でリッスンし、それに応じて行動する必要があります。

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
    }
}

2 番目のリスナーは、render イベントをチェックします。その場合、応答の結果がキャッシュされます。

このシステム (おそらく 100% のコピー/貼り付けではなく、概念) が機能するのResponseは、ルーティングまたはディスパッチ イベント中に を返すと、アプリケーションがアプリケーション フローを短絡させ、それ以上のリスナーのトリガーを停止するためです。その後、このレスポンスをそのまま提供します。

完全なページ(レイアウトを含む)になることに注意してください。それが必要ない場合 (コントローラーのみ)、ロジックをコントローラーに移動します。最初のイベント (現在のルート) はコントローラーのディスパッチになります。それを早めに聞いて、アクションの通常の実行を省略します。結果をキャッシュするには、リッスンするビュー レイヤーのレンダリング イベントを確認します。

/update: アプリでこの DRY を使用するための小さなモジュールを作成しました: SlmCache

于 2012-12-08T15:45:31.330 に答える