Буквально вчера обнаружил еще одну классную фишку в Smarty…
А было дело так. На сайте был довольно тяжелый подвал, в котором было сразу несколько нагруженных моментов (пара Wayfinder-ов, getResources с набивкой в шаблоны с использованием phpthumbOf-а и т.п.). При этом подвал был одинаковый для всех страниц сайта.
Конечно подвал был кешируемый, но все мы знаем, что кеш в MODX-е создается отдельно для каждой страницы. То есть при первом заходе на каждую страницу в отдельности, все равно подвал выполнялся полностью.
Ну я как обычно решил это дело оптимизировать, заменив подвал на кешируемый сниппет, в котором уже подгружал шаблон подвала, и кешировал его с помощью $modx->cacheManager. В таком случае шаблон выполнялся только один раз после полного сброса кеша, а во всех остальных случаях даже при первом заходе на страницу, подвал уже не выполнялся с нуля, а возвращался его код из кеша.
Конечно это позволяет значительно снизить нагрузку, но все равно имеется сразу несколько минусов:
1. Это все-таки сниппет. А как мы знаем, даже если это кешируемый элемент, MODX-парсер все равно будет тратить на него усилия при разборе кеша страницы.
2. Это просто не удобно. Создай сниппет, пропиши в нем код, подгрузи Smarty-шаблон и т.п. (да, я знаю про getCache и прочие кеш-акселераторы, но смотрим пункт 1).
3. Хотелось бы вообще исключить всякие сниппеты и т.п.
И вот тут я сначала подумал написать краткий плагин для Smarty, а потом подумал «а может в Smarty есть встроенные механизмы для этих задач?». И как оказалось, есть! Оказывается, если вызывать подшаблон с указанием ключа кеша, то для этого подшаблона будет создан индивидуальный кеш, и в дальнейшем при всех вызовах этого подшаблона, результат будет браться из кеша, если он есть. Пример вызова:
{include file="my_template.tpl" cache="my_cache_key"}
Вот и все. Не надо никаких сниппетов и т.п. Просто вызывали с указанием ключа кеша, и шаблон будет выполнен только один раз для всего сайта!
Я сразу объясню, почему я так долго тупил и не нашел это решение раньше. Дело в том, что в Smarty есть включение и отключение кеширования (и в modxSmarty это имеется в виде системной настройки). Но при включенном полном кешировании надо очень внимательно писать шаблоны, с указанием nocache во всех элементах, которые не должны кешироваться. Лично мне это не очень удобно, потому я отключаю кеширование Smarty, рассчитывая на кеширование самим MODX-ом (хотя с включенным Smarty-кешированием нагрузка реально резко падает). Но за это удобство (простые шаблоны) приходится платить цену — нагрузка при первом заходе на страницу. Вот я и думал, мол, отключил Смарти-кеширование и все, на Смарти рассчитывать уже не приходится. А вот как оказалось, что этот финт с указанием кеш-ключа работает даже тогда, когда глобальное кеширование Smarty отключено. И это офигенно! Распилили основной Smarty-шаблон на кешируемые блоки, указали для них кеш-ключи и все, не паримся — даже при первом заходе на новые страницы код будет браться из кеша. А в некешируемой части оставим только то, что действительно должно быть не кешироемо. Нагрузка упадет значительно.
И вот здесь мне приходит две мысли в голову:
1. Эти кеш-ключи можно динамически указывать. К примеру:
{include file="my_template.tpl" cache="cache_key_{$modx->resource->parent}"}
То есть здесь мы будем иметь различный кеш для различных родительских разделов.
{include file="my_template.tpl" cache="cache_key_page_{$smarty.get.page}"}
А это кеш для постраничности (само собой это простой пример. В более сложном варианте можно использовать параметры поиска и т.п.).
2. Единое меню с использованием javascript.
Эта тема вообще уже не раз всплывала. Особенно очень близкий по смыслу был вот этот топик.
Просто даже если брать во внимание вот это решение
(смотрите 2. Замена Wayfinder), все равно не круто получается, что для каждой страницы надо пробегаться по всему массиву и собирать конечное меню. А ведь можно просто выдать голое меню и средствами javascript уже пробежаться и собрать его в конечный вид. Для этого просто в шаблоне передает ID текущего документа, чтобы можно было в менюшке определить текущий документ и раздел.
В общем, вот такие мысли…