WordPress区块主题下如何覆写默认区块模板实现自定义文章类型单页
问题场景
- 当前使用基于新版区块结构构建的Twenty TwentyTwo全区块主题,自行开发插件注册了带若干自定义字段的自定义文章类型,需要创建专属单篇内容模板,在页面输出对应自定义字段值
- 模板文件使用传统PHP写法调用
get_header()、get_footer()时触发弃用报错,传统写法示例:
get_header(); // some content output get_footer();
- 具体报错信息:
弃用提示:自3.0.0版本起,未内置header.php的主题已被标记为弃用,暂无可用替代方案,请在你的主题中添加header.php模板文件。报错位置:/home/c/cv55478/public_html/wp-includes/functions.php 第5579行
调用get_footer()时会触发完全相同的弃用提示。
- 当前通过如下代码挂载自定义模板:
// customize template for single program page add_filter( 'single_template', 'ozzsf_single_program_template' ); function ozzsf_single_program_template( $single_template ) { global $post; if ( $post->post_type == 'program' ) { $program_template = plugin_dir_path( __FILE__ ) . 'templates/single-program.php'; if ( file_exists( $program_template ) ) { $single_template = $program_template; } } return $single_template; }
- 尝试将主题目录下的
twentytwentytwo/templates/single.html区块模板复制到插件目录调用,无法像主题内文件一样被正常编译解析 - 观察到最新版本WooCommerce仍使用PHP模板搭配
get_header()的传统写法,未触发上述警告,需要了解该现象原因,以及自定义文章类型单页模板覆写的正确方案
核心原因说明
- 报错根源:Twenty TwentyTwo是全站点编辑(FSE)区块主题,主题本身不存在传统经典主题的
header.php、footer.php文件,直接调用get_header()/get_footer()时WordPress找不到对应模板文件,就会抛出弃用提示。 - WooCommerce不触发报错的原因:WooCommerce内置了主题类型判断逻辑,检测到当前启用的是全区块主题时,不会直接调用传统的头尾加载函数,而是适配区块主题的渲染流程,只有在经典主题环境下才会走
get_header()/get_footer()的传统逻辑。 - 复制主题HTML区块模板到插件无法解析的原因:WordPress默认只会扫描当前启用主题(含子主题)目录下的
.html区块模板,不会自动识别、编译插件目录下的区块模板文件,未经过注册流程的HTML区块文件不会被正常解析。
正确实现方案
方案1:传统PHP模板兼容写法(和WooCommerce逻辑一致,开发成本最低)
直接修改自定义模板文件,增加主题类型判断,同时兼容区块主题和经典主题,不会触发弃用提示,自定义字段输出逻辑和传统WordPress开发完全一致:
<?php // 经典主题才调用传统头尾函数 if ( ! wp_is_block_theme() ) { get_header(); } else { // 区块主题手动加载头部资源和头部模板部件 wp_head(); block_template_part( 'header' ); } // 自定义内容输出区域 if ( have_posts() ) { while ( have_posts() ) { the_post(); // 输出文章基础内容 the_title( '<h1 class="program-title">', '</h1>' ); the_content(); // 输出自定义字段,替换为你自己的字段键名即可 $custom_field_val = get_post_meta( get_the_ID(), 'your_custom_field_key', true ); if ( $custom_field_val ) { echo '<div class="program-custom-meta">' . esc_html( $custom_field_val ) . '</div>'; } } } // 加载尾部结构 if ( wp_is_block_theme() ) { block_template_part( 'footer' ); wp_footer(); } else { get_footer(); }
方案2:原生区块模板挂载(和主题风格统一度最高)
如果需要完全适配Twenty TwentyTwo的区块渲染逻辑,可以按如下方式注册插件内的区块模板:
- 先通过过滤器注册自定义区块模板,指定适用的文章类型
- 模板加载时手动调用区块解析函数渲染HTML模板内容,自定义字段可以通过动态区块、内容占位符替换的方式输出
// 注册自定义区块模板 add_filter( 'theme_templates', 'ozzsf_register_program_template', 10, 4 ); function ozzsf_register_program_template( $templates, $theme, $post, $post_type ) { if ( $post_type === 'program' ) { $templates['single-program'] = '项目单页模板'; } return $templates; } // 加载插件内的区块模板 add_filter( 'template_include', 'ozzsf_render_program_template', 99 ); function ozzsf_render_program_template( $template ) { if ( is_singular( 'program' ) ) { $template_path = plugin_dir_path( __FILE__ ) . 'templates/single-program.html'; if ( file_exists( $template_path ) ) { wp_head(); block_template_part( 'header' ); // 解析并渲染区块模板内容 $template_content = file_get_contents( $template_path ); echo do_blocks( $template_content ); block_template_part( 'footer' ); wp_footer(); exit; } } return $template; }
内容的提问来源于stack exchange,提问作者Kirill Ozeritski
相关产品推荐
相关产品推荐

