Drupal如何跨Twig传递自定义块变量到渲染的视图块
问题根因
Twig中调用drupal_block()传入的第二个数组参数,是作为块插件的配置项传入的,不会自动映射为Views可直接读取的内置参数,因此无法在hook_views_pre_view中直接读取到product_type变量。另外直接修改$view->display_handler->display['display_options']数组的写法不会生效,Views要求通过官方提供的setOption()方法修改配置,才能触发配置校验、缓存处理等逻辑。
实现方案
方案1:保留现有Twig写法,通过钩子中转取值
不需要调整现有Twig模板的调用代码,通过两个钩子配合完成参数传递,稳定性最高:
- 首先在自定义模块中添加临时存储函数+块视图 alter 钩子,提前拿到传入的块配置:
/** * 临时存储视图块传入的自定义参数 */ function _mymodule_temp_view_params(string $key = NULL, mixed $value = NULL) { static $storage = []; if (!is_null($key) && !is_null($value)) { $storage[$key] = $value; } return is_null($key) ? $storage : ($storage[$key] ?? NULL); } /** * Implements hook_block_view_alter() */ function mymodule_block_view_alter(array &$build, \Drupal\Core\Block\BlockPluginInterface $block) { // 仅处理目标视图块,避免影响其他块 if ($block->getPluginId() === 'views_block:my-view-block_1') { $block_config = $block->getConfiguration(); if (!empty($block_config['product_type'])) { _mymodule_temp_view_params('product_type', $block_config['product_type']); } } }
- 修改原有
hook_views_pre_view逻辑,读取临时存储的参数完成过滤设置:
/** * Implements hook_views_pre_view() */ function mymodule_views_pre_view(&$view, &$display_id, &$args) { // 仅处理目标视图的对应显示 if ($view->id() === 'my_view' && $display_id === 'block_1') { $product_type = _mymodule_temp_view_params('product_type'); if ($product_type) { // 获取原有过滤器配置,避免覆盖其他过滤器 $filters = $view->display_handler->getOption('filters'); // 修改目标过滤项的默认值 $filters['field_product_type_target_id']['default_value'] = $product_type; // 存回配置,不要直接修改display下的原始数组 $view->display_handler->setOption('filters', $filters); } } }
方案2:使用Views原生上下文过滤(推荐,无需大量自定义代码)
这是Drupal Views推荐的传参方式,不需要写临时存储逻辑,维护成本更低:
- 调整Twig中的调用写法,将参数放到Views识别的
arguments节点下:
{{ drupal_block('views_block:my-view-block_1', { arguments: ['clothes'] }) }}
- 在视图编辑页,给对应块显示添加上下文过滤器,选择
产品类型(field_product_type)字段,根据需求配置「当过滤值不存在时」的逻辑(比如隐藏视图、显示所有结果、展示404等),保存视图即可。
如果需要额外自定义过滤逻辑,可以直接在hook_views_pre_view中读取$args数组拿到传入值:
function mymodule_views_pre_view(&$view, &$display_id, &$args) { if ($view->id() === 'my_view' && $display_id === 'block_1') { // 对应arguments数组的顺序,第一个参数索引为0 $product_type = $args[0] ?? NULL; // 自定义逻辑 } }
注意事项
- 所有视图相关的自定义逻辑必须加视图ID、显示ID判断,避免逻辑误用到站点其他视图上
- 视图块必须配置对应缓存上下文,否则会出现不同参数值下缓存串数据的问题,如果用上下文过滤方案,Views会自动添加对应缓存上下文;如果用方案1,需要手动给块添加
url或者自定义参数对应的缓存上下文 - 如果
product_type是多值字段,需要将传入值处理为数组格式再赋值给过滤器,不要传字符串
内容的提问来源于stack exchange,提问作者Asad ullah
相关产品推荐
相关产品推荐

