Подтвердить что ты не робот

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

Мы хотели бы добавить динамический блок на страницу продукта. Проблема в том, что страница продукта имеет полное кэширование страниц (и мы не можем отключить это из-за проблем с производительностью). Мы хотим отображать различную информацию на каждой странице продукта на основе зарегистрированной учетной записи пользователя и варьироваться от продукта к продукту.

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

Он работает в первые несколько раз, когда я перехожу на страницы продукта, но затем неожиданно начинает отображать страницу с ошибкой Magento, в которой говорится: "На веб-сайте произошла ошибка при получении http://www.mycompany.com/productpage.html Он может быть недоступен для обслуживания или неправильно настроен."

Вот что я сделал до сих пор. Я создал приложение/код/​​локальный/MyCompany/MyModule/PageCache/etc/config.xml для добавления MyCompany_PageCache_Model.

Затем я создал файл, который управляет кэшированием в app/code/local/MyCompany/MyModule/PageCache/Model/Container/MyFile.php с помощью следующих функций:

protected function _getCacheId()
{
    return 'CONSTANT_CACHE' . md5($this->_placeholder->getAttribute('cache_id'));
}

protected function _saveCache($data, $id, $tags = array(), $lifetime = null)
{
    return false;
}

protected function _renderBlock()
{
    $blockClass = $this->_placeholder->getAttribute('block');
    $template = $this->_placeholder->getAttribute('template');

    $block = new $blockClass;
    $block->setTemplate($template);
    $block->setLayout(Mage::app()->getLayout());
    return $block->toHtml();
}

Я также создал cache.xml под Каталогом /etc с моим заполнителем для CONSTANT_CACHE.

Является ли приведенный выше синтаксис неправильным, или есть более простой способ сделать это?

4b9b3361

Ответ 1

Обзор

Чтобы ответить, мне нужно сначала объяснить немного. Процесс Magento FPC знает четыре состояния.

  • Страница в кеше, без динамических блоков
  • Страница в кеше, динамические блоки в кэше
  • Страница в кеше, динамические блоки, не кэшированные
  • Страница не в кеше

Состояние 1 и 2 обрабатываются без полной инициализации приложения Magento. Для состояний 3 и 4 требуется, чтобы приложение было инициализировано и маршрутизирулось для обработки. По этой причине старайтесь выполнять запросы из состояний 1 и 2, если это возможно, в противном случае вы теряете значительную часть возможных улучшений FPC.

Состояние 1

Состояние 1 скучно с точки зрения разработчика, нечего делать, поэтому переходим к...

Состояние 2

В состоянии 2 страница содержит динамические блоки. Сейчас Magento не был полностью инициализирован.
Процессор FPC загружает кэшированную страницу и находит в ней местозаполнитель для динамического блока.
Анализируя местозаполнитель, процессор способен идентифицировать класс контейнера для динамического блока, создает его и называет applyWithoutApp($content) на нем. (Имя метода относится к тому факту, что приложение Magento еще не было инициализировано). Затем контейнер пытается загрузить содержимое динамического блока из кеша блока, используя ключ кеша, возвращаемый методом $this->_getCacheId().
Если ключ кеша будет возвращен и запись кэша может быть загружена, класс контейнера заменяет местозаполнитель в $content на выход кэшированного блока и FPC.
Пока что не было сделано никаких больших накладных расходов.

Состояние 3

Итак, applyWithoutApp($content) в состоянии 2 не удалось получить и доставить содержимое динамического блока, поэтому необходимо создать содержимое блока, хотя остальная часть страницы была найдена в FPC.
С этой целью модуль FPC устанавливает запрос на pagecache/request/process, и выполняется обычная инициализация и маршрутизация Magento.
Это означает, что накладные расходы производятся намного быстрее, чем состояние 2, хотя оно все же немного лучше, чем обычная загрузка страницы без FPC, потому что, например, переписывание URL-адресов пропущено.
Наконец, фронт-контроллер и стандартный маршрутизатор делегируют запрос методу RequestController::processAction().
Метод извлекает ранее созданный контейнерный класс для динамического блока и вызывает на нем applyInApp($content).
Этот метод запускает $this->_renderBlock(), чтобы создать экземпляр реального класса блока и вернуть его. Вы уже реализовали этот метод в соответствии с вашим вопросом. FPC теперь может заменить местозаполнитель блочным контентом и доставить страницу.
Одна вещь, о которой нужно знать, заключается в том, что это не обычный запрос страницы детали продукта, так, например, Mage::registry('current_product') недоступен! В зависимости от реализации блока это может повлиять на кэширование уровня блока или создание контента динамического блока. Я подозреваю, что это может быть причиной вашей проблемы, но я немного подойду к возможному обходному пути.

Состояние 4

В этом состоянии FPC не нашел запись кэша для запрошенной страницы, поэтому Magento генерирует страницу как обычно, например. вывод страницы детали продукта создается с помощью Mage_Catalog_ProductController::viewAction().
Все блоки, которые настроены для динамического отображения, в соответствии с cache.xml, завертываются в теги-заполнители.
Теги метки-заполнителя содержат аргументы, которые затем передаются объекту-контейнеру для шага 2 и 3. Единственными аргументами, которые всегда заданы, являются имена контейнеров и классов блоков. Но почти всегда устанавливаются a cache_id и a template.
В классе контейнера эти значения можно получить с помощью $this->_placeholder->getAttribute('cache_id') (как в методе _getCacheId() вашего контейнера).

Даже если вы замаскиваете большую часть этого длинного ответа, это может стать для вас интересным. Если вам нужны дополнительные значения для генерации идентификатора кеша блоков или вывода блока (например, идентификатор продукта или идентификатор клиента), , вы можете установить их как аргументы для заполнителя.

Для этого вам нужно установить их в массиве, возвращенном блочным методом getCacheKeyInfo(), с строкой в качестве ключа массива. Если вы используете индекс числового массива, они не будут установлены в качестве аргументов в заполнителе.

public function getCacheKeyInfo() {
    $info = parent::getCacheKeyInfo();
    $info['current_product_id'] = Mage::registry('current_product')->getId();
    $info['customer_id'] = Mage::getSingleton('customer/session')->getCustomerId();
    return $info;
}

Эти значения теперь доступны в классе контейнера, используя $this->_placeholder->getAttribute('current_product_id').

Заключение

Вероятно, вы не хотите переопределять _saveCache() в своем классе контейнера, чтобы вернуть false. Вместо этого укажите идентификатор клиента и идентификатор продукта в строке, возвращаемой _getCacheId(). Таким образом, каждый клиент получает свой собственный ввод в кэш. Некоторые издержки будут уменьшены, поскольку applyWithoutApp() может сохранять и загружать динамический блок из кеша (если страница просматривается дважды одним клиентом).

В _renderBlock() установите дополнительные значения, необходимые для того, чтобы блок мог создавать на нем содержимое, например.

$block->setProductId($this->_placeholder->getAttribute('current_product_id'));

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

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

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

Ответ 2

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

  • Если ваш обратный прокси-сервер поддерживает его, вы можете использовать ESI (Edge Side Includes) и соответствующим образом пометить свой шаблон. ESI позволяет вставлять маркер в сгенерированный HTML-код, куда должен идти персонализированный контент, тогда ваш прокси-сервер будет запрашивать только персонализированный контент с вашего подходящего пути контроллера вашего сервера приложений. Если вы используете Varnish, ESI доступен использовать. Расширение Lightspeed для Magento имеет функцию под названием Hole Punching, которая делает аналогичную вещь.
  • Если ESI или Hole Punching недоступны для вас, тогда другая опция позволяет кэшировать основную страницу в кеше полной страницы и использовать немного javascript для создания отдельного запроса Ajax и получения информации вам нужно.

Ответ 3

Я очень ценю ответ Виная. Кроме того, я бы посоветовал расширение FPC от Gordon Lesti, которое поддерживает сквозное отверстие. Вы можете получить его здесь

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

Я надеюсь, что это поможет кому-то, кто не так хорошо знаком с концепциями.

Ответ 4

Нет необходимости:

  $info['current_product_id'] = Mage::registry('current_product')->getId();

Вы можете использовать этот метод:

$this->_getProductId()

реализован в Enterprise_PageCache_Model_Container_Abstract