小工具(Widget)一直是 WordPress 主题中用于侧边栏、页脚等区域内容填充的重要方式。传统的小工具通过 PHP 类实现,继承 WP_Widget,在 functions.php 中注册。但随着 WordPress 引入了区块编辑器,小工具系统也经历了一次重大的转型。现在主题支持两种小工具模式:传统小工具和区块小工具。理解两者的区别以及如何开发自定义小工具,对主题开发者来说是一个重要的技能。

传统小工具的开发方式比较直接。创建一个继承 WP_Widget 的类,实现 __constructwidgetformupdate 四个方法。__construct 注册小工具的 ID、名称和描述;widget 输出前端 HTML;form 输出后台设置表单;update 保存设置数据。

一个典型的传统小工具代码结构如下:

class My_Custom_Widget extends WP_Widget {
    public function __construct() {
        parent::__construct(
            'my_custom_widget',
            '我的自定义小工具',
            array('description' => '这是一个自定义小工具')
        );
    }

    public function widget($args, $instance) {
        echo $args['before_widget'];
        if (!empty($instance['title'])) {
            echo $args['before_title'] . $instance['title'] . $args['after_title'];
        }
        echo '<p>' . $instance['content'] . '</p>';
        echo $args['after_widget'];
    }

    public function form($instance) {
        $title = !empty($instance['title']) ? $instance['title'] : '';
        $content = !empty($instance['content']) ? $instance['content'] : '';
        ?>
        <p>
            <label for="<?php echo $this->get_field_id('title'); ?>">标题:</label>
            <input class="widefat" id="<?php echo $this->get_field_id('title'); ?>" 
                   name="<?php echo $this->get_field_name('title'); ?>" type="text" 
                   value="<?php echo esc_attr($title); ?>" />
        </p>
        <p>
            <label for="<?php echo $this->get_field_id('content'); ?>">内容:</label>
            <textarea class="widefat" id="<?php echo $this->get_field_id('content'); ?>" 
                      name="<?php echo $this->get_field_name('content'); ?>"><?php echo esc_textarea($content); ?></textarea>
        </p>
        <?php
    }

    public function update($new_instance, $old_instance) {
        $instance = array();
        $instance['title'] = sanitize_text_field($new_instance['title']);
        $instance['content'] = sanitize_textarea_field($new_instance['content']);
        return $instance;
    }
}

add_action('widgets_init', function() {
    register_widget('My_Custom_Widget');
});

传统小工具的方式成熟稳定,完全兼容所有主题。但从 WordPress 5.8 开始,新的“区块小工具”系统允许用户在侧边栏中插入任何 Gutenberg 块,就像在页面编辑器中一样。这意味着用户可以在侧边栏自由组合段落、图片、按钮、最新文章等区块,而不局限于主题预设的小工具。

如果你想在主题中支持区块小工具,只需要在 functions.php 中添加一行:

php
复制
下载
add_theme_support('widgets-block-editor');

启用后,原来的小工具区域会变成区块编辑器界面,用户可以拖拽和排列区块。

对于开发者来说,如果你想创建“区块式小工具”,实际上就是创建一个自定义 Gutenberg 块,然后用户可以在任何区块小工具区域插入它。这个过程比传统小工具更复杂一些,涉及 JavaScript 开发,但能力也更强大。你可以创建带有丰富交互界面的小工具,实时预览效果。

在转型期间,传统小工具和区块小工具可以共存。如果你的主题需要同时兼容两种模式,可以检测当前是否启用了区块小工具:

if (function_exists('wp_use_widgets_block_editor')) {
    // 启用了区块小工具
} else {
    // 传统小工具模式
}

对于大多数用户来说,区块小工具提供了更丰富的页面构建能力。但对于那些需要固定布局、不希望用户随意改变样式的项目,传统小工具可能更合适,因为它限制了输入框的类型和数量,用户只能填写文字,不能改变结构。

小工具的数据存储方式也有所不同。传统小工具的数据存储在 wp_options 表的 widget_ 前缀选项中。区块小工具的数据存储在 wp_posts 表中,类型为 wp_block 或者作为 post_content 的一部分。如果你从传统小工具迁移到区块小工具,主题可能需要进行数据迁移。

在实际项目中,你可以根据用户需求决定使用哪种方式。对于内容驱动型的博客或新闻站,区块小工具能给编辑更多自由度。对于企业官网这种对设计一致性要求较高的项目,传统小工具的约束反而成了优点。