Drupal自定义管理子主题覆写内容类型编辑表单触发TypeError异常
问题成因
这个类型错误是Drupal主题钩子的匹配规则和form类钩子的特殊注册机制共同导致的:
- form类主题钩子和页面、节点类的钩子不同,所有带
__后缀的细分变体钩子,必须在表单自身的#theme属性数组中显式声明,才会被注入完整的表单渲染上下文。系统不会自动根据表单ID自动生成所有粒度的变体钩子并完成数据绑定。 - 你遇到异常的触发链路很清晰:
- 你写的预处理函数命名、或者templates目录下的Twig文件名,刚好匹配
form__node_very_basic_content_type_form这个细分钩子,主题检测到这个钩子存在后,自动将它标记为高优先级的匹配项。 - 渲染编辑表单时,系统优先匹配到你的自定义钩子,会为这个独立的细分钩子搭建单独的预处理执行链。但因为这个钩子没有被表单本身显式声明,执行链缺失了核心的
element变量注入环节,最终$variables['element']的值为null。 - 系统内置的
template_preprocess_form()函数执行到属性处理逻辑时,尝试把拿到的element参数传给Element::setAttributes(),因为收到的参数是null,直接触发类型校验报错。
- 你写的预处理函数命名、或者templates目录下的Twig文件名,刚好匹配
- 本质上,你以为自定义钩子会精准匹配当前表单,实际上因为form钩子的注册规则,系统把你写的自定义钩子当成了独立的空壳钩子,没有把真实的表单渲染数据传入。
解决方法
可根据实际需求选择对应方案操作:
- 方案1:改用通用节点表单钩子做条件判断(最稳妥,推荐)
- 先删除之前写的
mysite_admin_preprocess_form__node_very_basic_content_type_form预处理函数 - 清除templates目录下多余的
form--node-very-basic-content-type-form.html.twig文件 - 使用所有节点表单都会触发的通用预处理钩子,在函数内部判断当前表单是否为目标内容类型,再写对应逻辑:
function mysite_admin_preprocess_form(&$variables) { // 先确认当前渲染的是节点编辑表单 if (isset($variables['element']['#node']) && $variables['element']['#node']->getEntityTypeId() == 'node') { $node = $variables['element']['#node']; // 匹配目标内容类型 if ($node->bundle() == 'very_basic_content_type') { // 此处替换为你的实际预处理逻辑 ksm($variables); } } } - 先删除之前写的
- 方案2:如果确实需要为该内容类型表单单独做模板覆写,先显式注册自定义钩子
- 通过表单 alter 钩子给目标表单加上自定义主题钩子的声明,确保渲染上下文能正确传入:
做完这步后,你之前写的预处理函数、放置的Twig模板文件就能被正确调用,拿到完整的表单元素数据,不会再出现变量为null的报错。function mysite_admin_form_alter(&$form, $form_state, $form_id) { // 匹配目标内容类型的编辑表单ID if ($form_id == 'node_very_basic_content_type_form') { // 将自定义细分钩子放到#theme数组最前面,确保优先匹配 array_unshift($form['#theme'], 'form__node_very_basic_content_type_form'); } } - 基础配置校验
因为你的子主题是最小化配置,记得在mysite_admin.info.yml中确认正确声明了父主题依赖,避免子主题扫描钩子时缺失对父主题基础form预处理函数的继承:base theme: seven
内容的提问来源于stack exchange,提问作者Ejaz
相关产品推荐
相关产品推荐

