搜索全站
网站迁移 16 分钟阅读

WordPress 小工具区块化改造:新版小工具用法与恢复经典界面

WordPress 5.8 把小工具改成区块后,很多老站的小工具显示错乱。本文讲清新版区块小工具的使用逻辑、注册侧边栏的代码、恢复经典界面的两种方法,以及小工具内容丢失的找回方案。

U
UFO_PF 2022-08-14 · 阅读 16 分钟
Wo 网站迁移
阅读提示
本文约 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;
});

常见踩坑与失败案例

  1. 案例一:升级 5.8 后侧边栏样式全乱。原因是主题的 before_widget 包装(<div class="widget">)对区块小工具不生效了,CSS 选择器匹配不上。解决:给小工具区域外层加一个固定 class 的 wrapper,CSS 改用这个 wrapper 做选择器。
  2. 案例二:装了 Classic Widgets 后,某些新加的区块小工具不显示。两套机制的数据存储方式不同,新旧混用会出兼容问题。选定一种,不要来回切换。
  3. register_sidebar 的 id 用中文或大写:id 必须用小写字母、数字、连字符,用中文或下划线会导致小工具区域在新界面里不出现。
  4. 小工具里的 PHP 代码不执行:WordPress 小工具不解析 PHP。想在侧边栏跑逻辑,必须用自定义小工具类或短代码。
  5. 自定义 HTML 小工具被安全过滤:低权限用户(编辑、作者)保存的 <script> 会被 wp_kses 过滤。管理员不受限。
  6. 案例三:某站侧边栏放了”最新文章”小工具,缓存插件没排除动态区域,导致侧边栏内容几天不更新。要在缓存插件里开启”碎片缓存”或 AJAX 加载。
  7. 块主题没有小工具:块主题(Twenty Twenty-Four 等)完全不使用小工具,页头页脚走模板部件。这是正常设计,不是故障。

总结

小工具区块化之后,底层的 register_sidebar() / dynamic_sidebar() API 没变,变的是后台界面和内容存储。想回退就装官方 Classic Widgets 或一行 use_widgets_block_editor 过滤器,数据不会丢。要注意的两个坑:一是主题的 before_widget 包装对区块小工具失效,样式可能崩;二是新旧两套不要混用。如果站点是块主题,那就彻底忘掉小工具,改用模板部件。

U
UFO_PF作者

专注 WordPress 生态的实战作者,内容以「可复制、可验证」为第一原则。

留下你的想法

邮箱地址不会被公开。带 * 的为必填项。