本文约 3,674 字,预计阅读 10 分钟。文中命令与配置均经过实测,可直接参考执行。
引言:改了 home.php,前台却一点没变
很多人的第一次尝试是打开 home.php 调整代码,保存刷新,页面纹丝不动。或者更常见的:主题文档说”在 functions.php 里加一段 remove_action 就能去掉某个区块”,照抄之后区块依然在,于是怀疑文档写错了。
这两件事背后是同一个知识点没打通——首页到底用哪个模板文件,以及 remove_action 必须在 add_action 之后执行。lumen-mimangfei 这类模块化的主题,首页各区块通常不是写死在一个文件里,而是通过 action 钩子按优先级挂载,顺序由优先级数字决定,显示与否由 Customizer 里的开关(存于 theme_mod)决定。理解这两层,改布局就不用碰模板文件。
原理分析:模板优先级与钩子顺序
先看模板层:当”设置 → 阅读”里首页设为静态页面时,front-page.php 优先级最高;设为最新文章时才会用到 home.php,再回退到 index.php。所以你在 home.php 里改了半天没反应,很可能站点根本没走这个文件。
再看模块层:主题在首页模板里放若干 do_action( 'mimangfei_home_section' ) 之类的挂载点,各区块函数用 add_action( 'mimangfei_home_section', 'xxx', 10 ) 注册。数字小的先输出。要调整顺序,就是 remove_action 再用新的优先级 add_action 回去。
关键陷阱:子主题的 functions.php 先于父主题加载。如果你在子主题顶层直接 remove_action,此时父主题还没执行 add_action,自然删不掉。必须把移除动作延迟到一个父主题已完成注册的时机,比如挂在 after_setup_theme 上并给一个较大的优先级,或直接挂到 wp_loaded。
| 你的目的 | 推荐做法 | 风险 |
|---|---|---|
| 调换两个区块顺序 | remove_action + 新优先级 add_action |
优先级数值需与原注册不同 |
| 彻底移除某区块 | remove_action(需与原优先级一致) |
时机不对会失效 |
| 按条件显示 | 读取 get_theme_mod 或 is_front_page() 判断 |
与后台开关冲突 |
| 新增一个区块 | add_action 挂到同一钩子,配 get_template_part |
模板文件路径写错会静默失败 |
保姆级实操
- 先确认走哪个模板:在主题里看有没有
front-page.php;用wp option get show_on_front确认首页是静态页还是文章列表。 - 找出模块钩子名:在
front-page.php里搜索do_action,记下钩子名与周围注释。 - 找出各区块的优先级:搜索
add_action( '钩子名',记录每个函数名与第三个参数(优先级)。 - 用延迟执行的方式移除:把移除逻辑包进一个挂在
after_setup_theme(优先级 20+)或wp_loaded上的函数。 - 用后台开关优先:能在 Customizer 里关掉的区块就别写代码,主题设置与代码双写最容易冲突。
- 新增区块用
get_template_part:保持模板文件独立,方便后续维护。 - 改完清缓存:静态化缓存会让你误判改动是否生效。
<?php
// 子主题 functions.php
// 注意:必须延迟执行,等父主题把 add_action 跑完再移除
add_action( 'wp_loaded', 'mimangfei_reorder_home_sections' );
function mimangfei_reorder_home_sections() {
$hook = 'lumen_home_sections';
// 移除原注册(优先级要与父主题一致,缺省为 10)
remove_action( $hook, 'lumen_home_slider', 10 );
remove_action( $hook, 'lumen_home_latest_posts', 20 );
// 用新的优先级重新排:文章列表提前,轮播靠后
add_action( $hook, 'lumen_home_latest_posts', 15 );
add_action( $hook, 'lumen_home_slider', 25 );
}
<?php
// front-page.php:模块化输出 + 后台开关
get_header();
$sections = array(
'slider' => __( '轮播', 'lumen-mimangfei' ),
'feature' => __( '推荐位', 'lumen-mimangfei' ),
'latest' => __( '最新文章', 'lumen-mimangfei' ),
);
foreach ( $sections as $slug => $label ) {
// 后台开关关闭的区块直接跳过
if ( ! get_theme_mod( 'lumen_show_' . $slug, true ) ) {
continue;
}
get_template_part( 'template-parts/home/section', $slug );
}
get_footer();
<?php
// 在 Customizer 里注册开关(只在自定义界面生效)
add_action( 'customize_register', 'mimangfei_home_toggles' );
function mimangfei_home_toggles( $wp_customize ) {
$wp_customize->add_setting( 'lumen_show_slider', array(
'default' => true,
'sanitize_callback' => 'wp_validate_boolean',
) );
$wp_customize->add_control( 'lumen_show_slider', array(
'label' => __( '显示首页轮播', 'lumen-mimangfei' ),
'section' => 'lumen_home_options',
'type' => 'checkbox',
) );
}
常见踩坑
- 在
home.php里改,但站点首页是静态页面,实际走front-page.php。 remove_action的优先级与父主题add_action时不一致(父主题用了 20,你写 10),移除无效。- 移除代码写在子主题顶层,执行时父主题尚未注册,函数没被删掉。
- 后台开关已关闭,代码又强制输出,两边打架,改哪边都像”没生效”。
- 案例:某站照着文档把
remove_action( 'lumen_home_sections', 'lumen_home_slider' )贴进子主题functions.php顶部,刷新后轮播仍在。原因是子主题functions.php在父主题之前加载,移除动作执行时父主题的add_action还没跑。改成挂在wp_loaded上后一次生效。 get_template_part的路径写成template-parts/home/section-slider.php(带了.php),实际应为template-parts/home/section+slider。- 改完没清页面缓存,反复怀疑代码有问题。
总结
首页布局改动的优先级:后台开关 > 钩子优先级调整 > 覆写模板文件。判断标准是”能用设置解决的不写代码,能改钩子的不复制模板”。行动清单:① 确认 show_on_front 与 front-page.php;② 记录原钩子优先级;③ 移除动作延迟到 wp_loaded;④ 新增模块走 get_template_part;⑤ 改完清缓存并在无痕窗口验证。延伸阅读 lumen-mimangfei 主题文章列表样式、lumen-mimangfei 主题特色图片设置 与 WordPress 子主题制作。
