Magento 1.9 Block Cache — предотвращение кэширования ключей формы в Mage Catalog Block View Product View

Привет, профессионалы Magento!

Я использовал механизм Magentos Block Cache для повышения производительности на страницах продуктов. Он отлично работал на Magento CE 1.6.2, но теперь я обновляюсь до CE 1.9.0.1, и кэширование блоков не работает с новыми ключами форм Magentos.

Страницы продукта все еще кэшируются, но они естественным образом кэшируются, включая новый ключ формы в действиях форм. Когда другой пользователь пытается добавить товары в корзину, это не сработает, потому что ключ формы другого пользователя был закэширован. Таким образом, товар не добавляется, а корзина остается пустой.

Есть ли способ внедрить ключ формы в кешированный код или другой способ кеширования страниц продукта?

Методы кэширования в моем расширенном Mage_Catalog_Block_Product_View выглядят так:

protected function _construct()
{
        $this->addData(array(
            'cache_tags'        => array(Mage_Catalog_Model_Product::CACHE_TAG . "_" . $this->getProduct()->getId()),
        ));
}

public function getCacheKey()
{
    if (!$this->hasData('cache_key')) {
        //$cacheKey = LAYOUTNAME_STORE+ID_PRODUCT+ID
        $cacheKey = $this->getNameInLayout().'_STORE'.Mage::app()->getStore()->getId().'_PRODUCT'.$this->getProduct()->getId();         
        $this->setCacheKey($cacheKey);
    }
    return $this->getData('cache_key');
}

public function getCacheLifetime()
{     
      if($this->getNameInLayout()!='product.info') return null;
      if(!$this->cacheEnabled()) return null;         
      return 9999999999;
}

public static function cacheEnabled() {
    return true;
}   

person ibo_s    schedule 04.08.2014    source источник


Ответы (2)


На данный момент я нашел быстрое исправление, но все еще ищу лучшие решения. На данный момент я добавил метод _afterToHtml($html) в свой расширенный блок и внедрил form_key перед возвратом html из кеша. Если кому-то еще нужно это быстрое исправление, убедитесь, что условие if верно. Это гарантирует, что это делается только в блоке, который я действительно кэширую, а не в других блоках просмотра продукта.

Итак, это мое текущее быстрое исправление:

public function _afterToHtml($html) {
    if($this->getNameInLayout() == 'product.info') {
        $formkey = Mage::getSingleton('core/session')->getFormKey();
        $formkey = "/form_key/".$formkey."/";        
        $html = preg_replace("/\/form_key\/[a-zA-Z0-9,.-]+\//", $formkey, $html); 
    }  
    return parent::_afterToHtml($html);
}

Я думаю о переключении на полный кеш страниц в будущем, но исправить это было бы неплохо, так как настройка другого метода кеша также занимает много времени.

Поэтому, пожалуйста, помогите, если у вас есть идея получше, чем это грязное быстрое решение.

person ibo_s    schedule 04.08.2014

Я думаю, что я построил лучшее исправление. Я исправляю сразу весь вывод HTML, а также исправляю поля form_key в скрытых вводах формы.

Мое расширение прослушивает событие controller_front_send_response_before. Метод controllerFrontSendResponseBefore в app/code/community/JeroenVermeulen/BlockCache/Model/Observer.php

https://github.com/jeroenvermeulen/jeroenvermeulen-blockcache/

Лучше использовать события вместо переопределений, потому что у вас нет риска того, что два расширения переопределят одну и ту же основную функциональность. Событие также с большей вероятностью будет работать после обновления Magento.

person Jeroen Vermeulen - MageHost    schedule 28.08.2014
comment
Примечание. Существует также специальный Stack Exchange для Magento: magento.stackexchange.com. - person Jeroen Vermeulen - MageHost; 28.08.2014
comment
Привет, Jeroen, я согласен с тем, что подключение к событию, как правило, лучше, чем переопределение классов, но я не уверен, что ваше решение действительно лучше для этого сценария. В моем случае мне действительно нужно переопределить класс из-за методов кэширования, которые мне нужно переопределить. Если другое расширение переопределит тот же класс, мне придется их объединить... Я знаю об этом. Но в данный момент ваше решение кажется мне чем-то вроде удара кувалдой по ореху. У меня была проблема только с этим блоком, потому что я использую кеширование. Где вам нужно было заменить form_keys? Действительно нужно отредактировать весь ответ? - person ibo_s; 04.09.2014
comment
Что ж, использование событий вместо переопределений становится все более и более популярным, потому что это предотвращает конфликты между расширениями. Поскольку я очень рано использую легковесный оператор is_a(), наблюдатель блока не очень тяжелый. Поскольку я извлекаю все содержимое страниц категорий и сведений о продуктах из кеша, ключ формы необходимо заменить в содержимом, иначе кнопки «Добавить в корзину» не работают в Magento › 1.8 - person Jeroen Vermeulen - MageHost; 09.09.2014
comment
Не могли бы вы подсказать, что вы имеете в виду под оператором is_a()? Что-то вроде «instanceof»? Это функция Magento? - person ibo_s; 22.09.2014
comment
Вы правы, это что-то вроде instanceof. Дополнительная информация: Руководство по PHP. Я обнаружил несколько недель назад, что instanceof работает в 2 раза быстрее, поэтому я переключился на использование instanceof в своем расширении. - person Jeroen Vermeulen - MageHost; 24.09.2014