使用get_template_part与template_redirect导致WordPress内容重复
问题根源分析
你遇到的内容重复问题,核心原因是**template_redirect钩子的使用方式不对**:
这个钩子是在WordPress确定要加载的模板之后、实际渲染模板之前触发的。你在钩子函数里直接调用get_template_part('coav-search', 'lucky'),相当于额外输出了一次模板内容;而当你访问使用coav-search.php作为模板的页面时,WordPress本身已经会自动加载这个模板,所以就出现了“一次在页脚上方(正常模板加载)、一次在页脚下方(钩子触发的额外输出)”的重复问题。
另外,你通过set_query_var传递变量的逻辑没问题,但完全不需要通过钩子来做——自定义页面模板本身可以直接处理变量或接收表单数据。
解决方案
方案1:移除多余的钩子,让模板正常加载(推荐)
直接删掉functions.php里的form_coav_date函数及对应的add_action,把变量定义和表单处理逻辑放到模板里,或者用更规范的表单处理钩子:
修改后的functions.php
<?php function theme_enqueue_styles() { wp_enqueue_style( 'parent-style', get_template_directory_uri() . '/style.css' ); } add_action( 'wp_enqueue_scripts', 'theme_enqueue_styles' ); // 专门处理表单提交的函数(适配登录/未登录用户) function handle_coav_search_form() { // 验证表单请求,防止CSRF攻击(可以结合WordPress的nonce) if (isset($_POST['coav_search_nonce']) && wp_verify_nonce($_POST['coav_search_nonce'], 'coav_search_action')) { // 这里写你的表单处理逻辑,比如接收参数、验证、存储等 $form_data = $_POST['your_form_field'] ?? ''; // 把处理结果传递给模板 set_query_var('coav_form_result', "已收到你的提交:{$form_data}"); } } // 绑定表单处理的钩子(表单action要指向admin-post.php) add_action('admin_post_coav_search_form', 'handle_coav_search_form'); add_action('admin_post_nopriv_coav_search_form', 'handle_coav_search_form');
修改后的coav-search.php
/* Template Name: coav-search */ get_header(); // 获取表单处理结果(默认空值) $form_result = get_query_var('coav_form_result', ''); // 直接在模板里定义变量,不需要通过钩子传递 $lucky = 'lucky'; echo '<div style="text-align:center;margin:20px 0;">'; echo '<p>'; echo 'Hello im the custom content, im very ' . $lucky . ' :)'; // 显示表单处理结果(如果有) if (!empty($form_result)) { echo '<br>' . $form_result; } echo '</p>'; // 你的表单代码(注意action和nonce的设置) echo '<form action="' . admin_url('admin-post.php') . '" method="post">'; // 必须的action参数,对应钩子里的标识 echo '<input type="hidden" name="action" value="coav_search_form">'; // 添加WordPress安全验证nonce echo wp_nonce_field('coav_search_action', 'coav_search_nonce', true, false); // 其他表单字段 echo '<input type="text" name="your_form_field" placeholder="输入内容">'; echo '<button type="submit">提交</button>'; echo '</form>'; echo '</div>'; get_footer();
方案2:临时调试用——钩子仅传递变量,不输出模板
如果你暂时不想大改代码,可以修改钩子函数,只传递变量而不调用模板:
function form_coav_date() { // 只在当前页面使用coav-search模板时传递变量 if (is_page_template('coav-search.php')) { $lucky = 'lucky'; set_query_var( 'lucky', $lucky ); // 删掉get_template_part,避免重复输出 } } add_action('template_redirect', 'form_coav_date');
关键总结
WordPress的自定义页面模板会被自动加载,不需要通过钩子手动调用输出。钩子应该用来处理逻辑(比如表单提交、数据处理),而不是直接渲染模板内容——这才是符合WordPress开发规范的写法。
内容的提问来源于stack exchange,提问作者True-Slimen
相关产品推荐
相关产品推荐

