Рейтинг:1

Render view inside block with caching

флаг lc

My setup is a bit unconventional. I have a view displaying a block, relying on a contextual filter (let's call it product ID). I also have a custom block that renders this view programmatically because I need to include this block in multiple places on the page and I have some custom logic that pulls the actual product ID to call the view with. Basically:

$view = Views::getView('view_id'); 
$args = ['product_id' => $whatever_product];
return $view->buildRenderable('views_block_id', $args);

The process basically works but, as usual, I'll have problems when there are several such blocks on the page. Views only caches using the block id as a cache tag, so the first rendered view gets cached and displayed in all places. Naturally, switching off the cache would work:

return $view->buildRenderable('views_block_id', $args, FALSE);

but not exactly what I have in mind, I don't want to lose the benefits of caching.

My initial thought was quite simple, let's use custom cache tags in the view, thanks to views_custom_cache_tag. So I did, including the argument from the contextual filter:

views_block:view_id-views_block_id
custom:{{ arguments.product_id }}

But it still doesn't work.

Is there any other way I missed? I can't push new cache tags right before I try to render the view. The usual view hooks don't get called in this case (the second block already gets the cached variant, without even bothering to go near the hooks).

4uk4 avatar
флаг cn
*Естественно, отключение кеша сработает* `return $view->buildRenderable('views_block_id', $args, FALSE);`. Если это работает, то используйте его. Вам не нужно кэшировать визуализированный результат представления, когда вы находитесь в блоке, который кэшируется сам по себе.
флаг lc
Если у меня есть один и тот же блок дважды на странице, которая ссылается на другой продукт, что ж, я не буду очень рад, если блок кэшируется с одним из них. :-) Подумайте об этом, если блок кэширует себя со своим собственным добавленным идентификатором экземпляра, а не только с общим...
флаг lc
Хорошо, спасибо, если вы скопируете то же самое в ответ, я буду рад принять его.
Рейтинг:2
флаг cn

В блоке можно отключить кеширование отрендеренного View в ViewExecutable:: buildRenderable:

$view->buildRenderable('views_block_id', $args, FALSE)

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

Кстати, кэш-теги не участвуют при кэшировании вариантов одного и того же элемента.Это контролируется только ключами кеша и контекстами. С cache=FALSE вы отключаете ключи кеша, но не контексты, которые все равно должны подниматься до уровня блоков. Если контекст отсутствует, вы можете установить контекст кеша вручную, например, для маршрута или аргумента запроса пути URL, если от этого зависит идентификатор продукта.

Изменить: я удалил оператор return, потому что может потребоваться создать настоящий массив рендеринга со встроенным представлением.

флаг lc
В данном конкретном случае с возвратом работает нормально, это уже последняя строка функции `build()`. Спасибо.
steve avatar
флаг in
У меня есть то, что я _думаю_, аналогичная настройка, за исключением того, что я должен добавить, что мой единственный пользовательский блок может отображать один _или более_ блоков просмотра. На представления ссылаются из поля представления с несколькими значениями на узле, а в некоторых случаях на одно и то же представление ссылаются с другим отображением и аргументами. В этих случаях, когда на одно и то же представление ссылаются более одного раза, для всех них используется только первое отображение, и добавление аргумента FALSE к методу buildRenderable не решает эту проблему.

Ответить или комментировать

Большинство людей не понимают, что склонность к познанию нового открывает путь к обучению и улучшает межличностные связи. В исследованиях Элисон, например, хотя люди могли точно вспомнить, сколько вопросов было задано в их разговорах, они не чувствовали интуитивно связи между вопросами и симпатиями. В четырех исследованиях, в которых участники сами участвовали в разговорах или читали стенограммы чужих разговоров, люди, как правило, не осознавали, что задаваемый вопрос повлияет — или повлиял — на уровень дружбы между собеседниками.