2

当店のスタートページにウィジェットがあります。

ショップはFPCとブロックキャッシュを使用しています。

管理者がバックエンドのウィジェット設定を変更した場合、どうすればウィジェットの内容を更新できますか?

CacheKeyでウィジェットの構成データを使用することは可能ですか?

または、キャッシュの有効期間を非常に短く設定する必要がありますか?

編集:私自身の答えはキャッシュの有効期間を使用しています。ウィジェットインスタンスが編集されている場合にのみ、FPCからキャッシュされたブロックを明確にクリーンアップする方法は何でしょうか?

4

4 に答える 4

14

EE フル ページ キャッシュとウィジェット インスタンスのキャッシュ

(書き換えなし、無制限のキャッシュ寿命)

概要

最初のステップは、フロントエンド ウィジェット自体を作成することですが、フル ページ キャッシュが使用できる追加情報を提供します。
2 番目のステップは、ウィジェットのフル ページ キャッシュでホール パンチングを処理することです。
3 番目のステップは、このウィジェットが管理領域で変更された場合にのみ、ウィジェット キャッシュを自動的に消去することです。

ステップ 1: ウィジェットを作成する

まず、モジュールのetc/widget.xmlファイルを作成します。

<widgets>
    <netzarbeiter_test type="netzarbeiter_test/widget_test">
        <name>FPC Holepunch Cache Test</name>
        <description>Dummy test widget</description>
        <parameters>
            <!-- This is the important parameter here: -->
            <unique_id>
                <required>1</required>
            </unique_id>
            <example_text>
                <visible>1</visible>
                <label>Example Text Parameter</label>
                <type>text</type>
            </example_text>
        </parameters>
    </netzarbeiter_test>
</widgets>

パラメータに注意してください<unique_id>。入力の型や値は指定しません。Mage_Widget_Block_Adminhtml_Widget_Options::_addField()メソッド によって生成された値が自動的に入力されます。

    // Excerpt from Mage_Widget_Block_Adminhtml_Widget_Options::_addField()

    if ($values = $this->getWidgetValues()) {
        $data['value'] = (isset($values[$fieldName]) ? $values[$fieldName] : '');
    }
    else {
        $data['value'] = $parameter->getValue();
        //prepare unique id value
        if ($fieldName == 'unique_id' && $data['value'] == '') {
            $data['value'] = md5(microtime(1));
        }
    }

この小さな宝石のおかげで、生成されたレイアウト xml にウィジェット ID を挿入するためにクラスを書き直す必要はありません。Mage_Widget_Model_Widget_Instance

次に、ウィジェット クラス自体を作成します。メソッドで が使用されてMage_Widget_Block_Interfaceいることを除いて、これはインターフェイスを実装する単なる通常のブロック インスタンスです。 unique_idcacheKeyInfo

class Netzarbeiter_Test_Block_Widget_Test
    extends Mage_Core_Block_Abstract
    implements Mage_Widget_Block_Interface
{
    public function getCacheKeyInfo()
    {
        $info = parent::getCacheKeyInfo();
        if ($id = $this->getData('unique_id')) {
            // Because the array key is a string, it will be added to the FPC placeholder
            // parameters. That is how the FPC container can access it (see below).
            $info['unique_id'] =  (string) $id;
        }
        return $info;
    }

    protected function _toHtml()
    {
        // The FPC was completely cleared (or not created yet), 
        // recreate the widget parameter cache
        if (! $this->getFullPageCacheEnvironment() && $this->getUniqueId()) {
            $id = Netzarbeiter_Test_Model_Fpc_Container_Widget_Test::CACHE_PREFIX . $this->getUniqueId() . '_params';
            Enterprise_PageCache_Model_Cache::getCacheInstance()->save(serialize($this->getData()), $id);
        }
        // Just some dummy output to display the text parameter and the render time
        $time = now();
        $textParam = $this->escapeHtml($this->getExampleText());
        return <<<EOF
<p><b>Render Time:</b> {$time}<br/>
<b>Example Text:</b> {$textParam}<br/></p>
EOF;
    }
}

管理インターフェイスからウィジェット インスタンスを追加すると、 widget.xmlunique_idで指定されたパラメータがレイアウト xml に追加されます (読みやすくするために書式が追加されます:

SELECT layout_update_id, handle, xml FROM core_layout_update;
+------------------+--------------------------+----------------------------------------------------------------------------------------------------+
| layout_update_id | handle                   | xml                                                                                                |
+------------------+--------------------------+----------------------------------------------------------------------------------------------------+
|               17 | catalog_category_layered | <reference name="left">
|                  |                          |     <block type="netzarbeiter_test/widget_test" name="2a3b55e13549e176709fc6c67a4a7bd8">
|                  |                          |         <action method="setData">
|                  |                          |             <name>unique_id</name>
|                  |                          |             <value>7fa2574145ef204fb6d179cfc604ac76</value>
|                  |                          |         </action>
|                  |                          |         <action method="setData">
|                  |                          |             <name>example_text</name>
|                  |                          |             <value>This is a String!</value>
|                  |                          |         </action>
|                  |                          |     </block>
|                  |                          | </reference>
+------------------+--------------------------+----------------------------------------------------------------------------------------------------+

これは、ブロック インスタンスがレイアウト xml レンダリングによって作成されるときはいつでも、unique_idブロック オブジェクトでパラメータが認識されることを意味します。

ステップ 2: フルページ キャッシュ ホール パンチング

etc/cache.xmlファイル を追加します。

<config>
    <placeholders>
        <cms_block_widget>
            <block>netzarbeiter_test/widget_test</block>
            <placeholder>WIDGET_FPC_TEST</placeholder>
            <container>Netzarbeiter_Test_Model_Fpc_Container_Widget_Test</container>
        </cms_block_widget>
    </placeholders>
</config>

次に、コンテナ クラスを作成します。

class Netzarbeiter_Test_Model_Fpc_Container_Widget_Test
    extends Enterprise_PageCache_Model_Container_Abstract
{
    const CACHE_PREFIX = 'TEST_WIDGET_';

    protected function _getCacheId()
    {
        return self::CACHE_PREFIX . $this->_placeholder->getAttribute('unique_id');
    }

    protected function _renderBlock()
    {
        $block = $this->_getPlaceHolderBlock();
        // Set any parameters from the placeholder on the block as needed.
        // See observer below where the current parameters are cached.
        $id = $this->_getCacheId() . '_params';
        if ($parameters = Enterprise_PageCache_Model_Cache::getCacheInstance()->load($id)) {
            $block->addData(unserialize($parameters));
            // Set environment information on block (used in _toHtml,
            // the params cache is recreated when not set)
            $block->setFullPageCacheEnvironment(true);
        }
        Mage::dispatchEvent('render_block', array('block' => $block, 'placeholder' => $this->_placeholder));
        return $block->toHtml();
    }
}

完全にキャッシュされたページ内でウィジェットを動的ブロックにするために必要な作業はこれだけです。しかし、これまでのところ、ウィジェット ブロックは無期限にキャッシュされています。キャッシュの更新を処理する必要があります。

ステップ 3: ウィジェット保存時のキャッシュ更新

*_save_commit_afterすべての Magento モデルがウィジェット インスタンスに固有に提供する自動イベントには、イベント オブザーバーを使用します。ウィジェット インスタンスが管理インターフェイスに保存されるたびにトリガーされます。

<adminhtml>
    <events>
        <widget_widget_instance_save_commit_after>
            <observers>
                <netzarbeiter_test>
                    <model>netzarbeiter_test/observer</model>
                    <method>widgetWidgetInstanceSaveCommitAfter</method>
                </netzarbeiter_test>
            </observers>
        </widget_widget_instance_save_commit_after>
    </events>
</adminhtml>

パズルの最後のピースはオブザーバー メソッドです。

public function widgetWidgetInstanceSaveCommitAfter(Varien_Event_Observer $observer)
{
    /** @var $widget Mage_Widget_Model_Widget_Instance */
    $widget = $observer->getEvent()->getObject();
    $parameters = $widget->getWidgetParameters();
    $uniqueId = isset($parameters['unique_id']) ? $parameters['unique_id'] : '';
    if (strlen($uniqueId)) {
        $id = Netzarbeiter_Test_Model_Fpc_Container_Widget_Test::CACHE_PREFIX . $uniqueId;
        Enterprise_PageCache_Model_Cache::getCacheInstance()->remove($id);
        $id = Netzarbeiter_Test_Model_Fpc_Container_Widget_Test::CACHE_PREFIX . $uniqueId . '_params';
        Enterprise_PageCache_Model_Cache::getCacheInstance()->save(serialize($parameters), $id);
    }
}

概要

これで、フロントエンドのインスタンスは、フル ページ キャッシュがアクティブ化されていても、保存されるたびに自動的に更新されます。それ以外の場合は常に、動的ブロックがキャッシュからフェッチされます。

編集: キャッシュされたウィジェット パラメーターの例をコードに追加しました。これは、以下のコメントで Alex が指摘したように、FPC エントリが存在する限りプレースホルダー引数が更新されないためです。
キャッシュを使用してウィジェット パラメータをブロックに渡すと、ウィジェット インスタンス モデルを書き換えたり、ブロックが動的にレンダリングされるときにウィジェット インスタンスをロードしたりすることを回避できます。

于 2012-07-28T09:46:44.780 に答える
0

唯一の可能性は、cache_lifetime パラメータを介してこれを行うことだと思います。したがって、これを約 30 秒に設定すると、30 秒ごとに現在の構成に基づいてウィジェットが更新されます。

パラメータが変更されたときにすぐにアイテムをキャッシュから削除する解決策が見つかりませんでした。

これは私がしたことです:

  1. まず、ウィジェット ブロックはウィジェット インスタンスの ID を知る必要があります。そのためには、1 つのモジュールで Mage_Widget_Model_Widget_Instance::generateLayoutUpdateXml を書き直す必要がありました。

    public function generateLayoutUpdateXml($blockReference, $templatePath = '')
    {
        $xml = parent::generateLayoutUpdateXml($blockReference, $templatePath);
        $injectXml = '<action method="setData"><name>widget_instance_id</name><value>' .     
              $this->getId() . '</value></action>';
        $xml = str_replace('</block>', $injectXml . '</block>', $xml);
        return $xml;
    }
    
  2. 私のウィジェットブロックでは、キャッシュライフタイムを非常に小さく設定して、二重キャッシュを回避しました:編集: FPC がブロックキャッシュを無効にしたため不要

    public function getCacheLifetime()
    {
        return 1;
    }
    
  3. 現在のテンプレートとウィジェット インスタンス IDをキャッシュ情報に含めます。文字列キーを持つこれらの配列エントリは、FPC プレースホルダーの属性にマップされていることがわかりました。

    public function getCacheKeyInfo()
    {
        $instanceId = $this->getWidgetInstanceId();
    
        return array(
            'MYBOX',
            Mage::app()->getStore()->getId(),
            (int)Mage::app()->getStore()->isCurrentlySecure(),
            Mage::getDesign()->getPackageName(),
            Mage::getDesign()->getTheme('template'),
            'widget_instance_id' => $instanceId,
            'template' => $this->getTemplate(),
        );
    }
    
  4. ここで、このウィジェット用に独自の FPC プレースホルダーを作成する必要があります。このプレースホルダーは、ウィジェット インスタンスの現在の構成を読み込み、ウィジェットをレンダリングします。

    class MyCompany_PageCache_Model_Container_WidgetInstance
        extends Enterprise_PageCache_Model_Container_Abstract
    {
        protected function _renderBlock()
        {
            $instanceId = $this->_placeholder->getAttribute('widget_instance_id');
            $widgetInstance = Mage::getModel('widget/widget_instance')->load($instanceId);
            if($widgetInstance->getId()) {
                Mage::logException( new Exception('Widget Instance '.$instanceId.' not         found') );
            }
            $data = $widgetInstance->getWidgetParameters();
    
            $block = $this->_placeholder->getAttribute('block');
    
            $name = $this->_placeholder->getAttribute('name');
            $template = $this->_placeholder->getAttribute('template');
    
            $block = new $block;
            $block->setTemplate($template);
            if ($name !== null) {
                $block->setNameInLayout($name);
            }
            $block->setLayout(Mage::app()->getLayout());
            $block->setData($data);
    
    
            return $block->toHtml();
        }
        }
    
  5. このプレースホルダーに cache.xml 構成を追加する必要があります。

    <mycompany_mybox>
        <block>mycompany_mybox/widget</block>
        <placeholder>MYCOMPANY_MYBOX_WIDGET</placeholder>
        <container>MyCompany_PageCache_Model_Container_WidgetInstance</container>
        <cache_lifetime>30</cache_lifetime>
    </mycompany_mybox>
    
  6. 最後に、新しいレイアウト xml が生成されるように、ウィジェットをバックエンドに一度保存する必要があります。

于 2012-07-12T12:27:10.877 に答える
0

次のアプローチを試してください:

  1. モジュールでオーバーライドEnterprise_PageCache_Model_Validatorします。
  2. このクラスの配列に追加Mage_Widget_Block_Interfaceします。protected $_dataChangeDependency

  3. protected function _getObjectClasses($object)次のように書き換えます。


/**
 * Get list of all classes related with object instance
 *
 * @param $object
 * @return array
 */
protected function _getObjectClasses($object)
{
    $classes = array();
    if (is_object($object)) {
        $classes[] = get_class($object);
        $classes = array_merge($classes, class_implements($object), class_parents    ($object));
    }
    return $classes;
}
于 2012-07-19T12:59:32.563 に答える
0

メソッドを実装し、getCacheKeyInfoいくつかのブロック固有の値を使用して一意のハッシュを生成できます。

Magento EEでは、これをブロックで見ることができますEnterprise_Banner_Block_Widget_Banner

于 2012-07-12T07:56:05.790 に答える