Ответ 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, даже при создании пользовательских динамических блоков. Я надеюсь, что этой информации достаточно, чтобы вы могли отслеживать проблему, которую вы описываете, и исправить ее.