本文约 6,090 字,预计阅读 16 分钟。文中命令与配置均经过实测,可直接参考执行。
引言:升级之后,侧边栏乱了
WordPress 5.8 发布后,外观 → 小工具 从原来的”拖拽小工具到侧边栏”变成了一个区块编辑界面。升级后常见的现象:
- 原来配置好的小工具还在,但样式全变了;
- 第三方插件的小工具(老式
WP_Widget类)找不到了; - 想加个自定义 HTML 侧边栏,不知道在哪加;
- 用代码注册的小工具区域在新界面里显示为空白。
这一篇把新旧两套机制都讲清楚,包括怎么回退。
原理分析:两套机制并存
经典小工具机制:
// 注册侧边栏
register_sidebar( array(
'name' => '文章侧边栏',
'id' => 'sidebar-1',
'description' => '显示在文章页右侧',
'before_widget' => '<div class="widget %2$s">',
'after_widget' => '</div>',
'before_title' => '<h3 class="widget-title">',
'after_title' => '</h3>',
) );
// 主题里输出
dynamic_sidebar( 'sidebar-1' );
小工具实例存在 wp_options 表的 widget_* 选项里,是序列化数组。
区块小工具机制(5.8+):
同样的 register_sidebar() 注册的区域,但内容变成区块 HTML,存在 wp_posts 里 post_type = wp_block,post_name 类似 wp-widget-sidebar-1。
wp post list --post_type=wp_block --fields=ID,post_name,post_title
关键点:register_sidebar() 和 dynamic_sidebar() 这套 API 没有变,变的只是后台的编辑界面和内容存储格式。所以主题代码不用改,改的是管理方式和内容。
新界面里,老式 WP_Widget 类注册的小工具会被包进”传统小工具”区块(Legacy Widget),继续能用,但样式可能和主题的设计不匹配——因为主题的 before_widget / after_widget 包装对区块小工具不生效了。
保姆级实操
一、新界面怎么用
外观 → 小工具 → 左侧选择要编辑的小工具区域 → 用区块编辑器添加区块(搜索、最新文章、分类、自定义 HTML、导航、图片等)→ 保存。
新版的好处:可以直接用所有区块(包括组、列、按钮、社交图标),排版自由度远超老小工具。
二、注册多个侧边栏(代码)
add_action( 'widgets_init', 'mmf_register_sidebars' );
function mmf_register_sidebars() {
// 通用侧边栏
register_sidebar( array(
'name' => '通用侧边栏',
'id' => 'sidebar-main',
'before_widget' => '<section id="%1$s" class="widget %2$s">',
'after_widget' => '</section>',
'before_title' => '<h3 class="widget-title">',
'after_title' => '</h3>',
) );
// 页脚三栏
for ( $i = 1; $i <= 3; $i++ ) {
register_sidebar( array(
'name' => sprintf( '页脚第 %d 栏', $i ),
'id' => 'footer-' . $i,
'before_widget' => '<div class="footer-widget">',
'after_widget' => '</div>',
'before_title' => '<h4>',
'after_title' => '</h4>',
) );
}
}
主题模板里输出:
<?php if ( is_active_sidebar( 'sidebar-main' ) ) : ?>
<aside class="site-sidebar">
<?php dynamic_sidebar( 'sidebar-main' ); ?>
</aside>
<?php endif; ?>
页脚:
<div class="footer-cols">
<?php for ( $i = 1; $i <= 3; $i++ ) : ?>
<div class="footer-col">
<?php dynamic_sidebar( 'footer-' . $i ); ?>
</div>
<?php endfor; ?>
</div>
三、恢复经典小工具界面
方法 A:装官方插件 Classic Widgets
插件目录搜 “Classic Widgets”,作者 WordPress Contributors。装完自动恢复旧的拖拽界面,不需要任何配置,也不丢数据——两套界面读写的是兼容的数据。
方法 B:代码
add_filter( 'use_widgets_block_editor', '__return_false' );
加到子主题 functions.php 即可。
四、找回”消失”的小工具内容
升级后如果侧边栏变空,内容通常是还在的,只是没被正确迁移。检查:
SELECT option_name, LENGTH(option_value) FROM wp_options
WHERE option_name LIKE 'widget_%';
wp option list --search="widget_*" --fields=option_name
如果 widget_* 里还有数据,说明经典小工具的实例还在,只是新界面没渲染。装 Classic Widgets 就能看到。
五、自定义小工具(代码方式,新旧都兼容)
class MMF_Author_Widget extends WP_Widget {
public function __construct() {
parent::__construct(
'mmf_author_widget',
'作者简介卡片',
array( 'description' => '显示当前文章作者的信息' )
);
}
public function widget( $args, $instance ) {
echo $args['before_widget'];
if ( ! empty( $instance['title'] ) ) {
echo $args['before_title'] . esc_html( $instance['title'] ) . $args['after_title'];
}
echo '<div class="author-card">';
echo get_avatar( get_the_author_meta( 'ID' ), 64 );
echo '<p>' . esc_html( get_the_author_meta( 'display_name' ) ) . '</p>';
echo '<p>' . esc_html( get_the_author_meta( 'description' ) ) . '</p>';
echo '</div>';
echo $args['after_widget'];
}
public function form( $instance ) {
$title = ! empty( $instance['title'] ) ? $instance['title'] : '关于作者';
?>
<p>
<label for="<?php echo esc_attr( $this->get_field_id( 'title' ) ); ?>">标题:</label>
<input class="widefat"
id="<?php echo esc_attr( $this->get_field_id( 'title' ) ); ?>"
name="<?php echo esc_attr( $this->get_field_name( 'title' ) ); ?>"
type="text" value="<?php echo esc_attr( $title ); ?>">
</p>
<?php
}
public function update( $new_instance, $old_instance ) {
$instance = array();
$instance['title'] = sanitize_text_field( $new_instance['title'] );
return $instance;
}
}
add_action( 'widgets_init', function() {
register_widget( 'MMF_Author_Widget' );
});
六、只在某些页面显示某个侧边栏
装插件 “Widget Options” 或 “Conditional Widgets”,可以按页面类型、分类、设备(手机/桌面)控制显示。
代码方式:
add_filter( 'sidebars_widgets', function( $sidebars ) {
if ( is_front_page() ) {
// 首页不显示侧边栏
$sidebars['sidebar-main'] = array();
}
return $sidebars;
});
常见踩坑与失败案例
- 案例一:升级 5.8 后侧边栏样式全乱。原因是主题的
before_widget包装(<div class="widget">)对区块小工具不生效了,CSS 选择器匹配不上。解决:给小工具区域外层加一个固定 class 的 wrapper,CSS 改用这个 wrapper 做选择器。 - 案例二:装了 Classic Widgets 后,某些新加的区块小工具不显示。两套机制的数据存储方式不同,新旧混用会出兼容问题。选定一种,不要来回切换。
register_sidebar的 id 用中文或大写:id必须用小写字母、数字、连字符,用中文或下划线会导致小工具区域在新界面里不出现。- 小工具里的 PHP 代码不执行:WordPress 小工具不解析 PHP。想在侧边栏跑逻辑,必须用自定义小工具类或短代码。
- 自定义 HTML 小工具被安全过滤:低权限用户(编辑、作者)保存的
<script>会被wp_kses过滤。管理员不受限。 - 案例三:某站侧边栏放了”最新文章”小工具,缓存插件没排除动态区域,导致侧边栏内容几天不更新。要在缓存插件里开启”碎片缓存”或 AJAX 加载。
- 块主题没有小工具:块主题(Twenty Twenty-Four 等)完全不使用小工具,页头页脚走模板部件。这是正常设计,不是故障。
总结
小工具区块化之后,底层的 register_sidebar() / dynamic_sidebar() API 没变,变的是后台界面和内容存储。想回退就装官方 Classic Widgets 或一行 use_widgets_block_editor 过滤器,数据不会丢。要注意的两个坑:一是主题的 before_widget 包装对区块小工具失效,样式可能崩;二是新旧两套不要混用。如果站点是块主题,那就彻底忘掉小工具,改用模板部件。
