WordPress源码深度解析之:`WordPress`的`customizer API`:`WP_Customize_Manager`的底层实现。

各位观众老爷,晚上好!我是老码,今晚咱们来聊聊 WordPress 的 Customizer API,特别是它背后的扛把子—— WP_Customize_Manager。这玩意儿,说白了,就是 WordPress 后台“外观 -> 自定义”那个界面的灵魂人物。

一、Customizer API 是个啥?

想象一下,你是个网站主,想改改网站的颜色、背景、logo,总不能每次都改代码吧?Customizer API 就是为了解决这个问题而生的。它提供了一个可视化的界面,让用户可以实时预览修改效果,满意了再保存。

这玩意儿的核心理念就是:实时预览、配置持久化

二、WP_Customize_Manager:幕后大 Boss

WP_Customize_Manager 类,是 Customizer API 的核心,负责管理所有的自定义选项(settings)、控件(controls)、面板(panels)和分区(sections)。 它负责初始化 Customizer,加载主题支持,处理 Ajax 请求,并最终保存用户的更改。

简单来说,它就是个项目经理,管理着 Customizer 这个大项目的所有细节。

三、WP_Customize_Manager 的初始化:生命的开始

Customizer 的生命周期从 WP_Customize_Manager 的初始化开始。这个过程主要发生在 wp-includes/class-wp-customize-manager.php 文件中。

global $wp_customize; // 确保全局变量存在

if ( isset( $wp_customize ) ) {
    return; // 防止重复初始化
}

require_once ABSPATH . WPINC . '/class-wp-customize-setting.php';
require_once ABSPATH . WPINC . '/class-wp-customize-control.php';
require_once ABSPATH . WPINC . '/class-wp-customize-section.php';
require_once ABSPATH . WPINC . '/class-wp-customize-panel.php';

$wp_customize = new WP_Customize_Manager();

这段代码干了几件事:

  1. 检查全局变量 $wp_customize 是否已存在,防止多次初始化。
  2. 引入相关的类文件:WP_Customize_Setting, WP_Customize_Control, WP_Customize_Section, WP_Customize_Panel。 这些是 Customizer 的四大金刚。
  3. 实例化 WP_Customize_Manager 类,并赋值给全局变量 $wp_customize

四、注册自定义选项: 添加“可调”的旋钮

Customizer 的核心就是让用户可以调整各种选项。这些选项,在 Customizer API 中被称为 Settings。WP_Customize_Manager 提供了 add_setting() 方法来注册这些选项。

/**
 * Adds a customize setting.
 *
 * @since 4.0.0
 *
 * @param string $id         A specific ID of the setting.
 * @param array  $args       Setting arguments.
 * @return WP_Customize_Setting|null The setting object, if successfully added. Null on failure.
 */
public function add_setting( $id, $args = array() ) {
    // ... 省略代码 ...
}

这个方法接受两个参数:

  • $id: 设置的唯一 ID,就像你的身份证号一样。
  • $args: 一个包含设置参数的数组,比如默认值、传输方式(refresh 或 postMessage)等等。

举个例子:

$wp_customize->add_setting(
    'my_theme_accent_color',
    array(
        'default'   => '#007bff',
        'transport' => 'postMessage', // 使用 postMessage 实现实时预览
    )
);

这段代码注册了一个名为 my_theme_accent_color 的设置,默认值是 #007bff,并且使用 postMessage 传输方式,这意味着修改这个设置时,会通过 JavaScript 实时更新预览窗口。

五、添加控件: 给用户提供“操作杆”

有了设置,还得有控件让用户来调整。控件可以是颜色选择器、文本框、下拉菜单等等。WP_Customize_Manager 提供了 add_control() 方法来添加控件。

/**
 * Adds a customize control.
 *
 * @since 4.0.0
 *
 * @param string|WP_Customize_Control $id      A specific ID of the control.
 * @param array                       $args    Control arguments.
 * @return WP_Customize_Control|null The control object, if successfully added. Null on failure.
 */
public function add_control( $id, $args = array() ) {
    // ... 省略代码 ...
}

参数和 add_setting() 类似:

  • $id: 控件的唯一 ID。
  • $args: 一个包含控件参数的数组,比如标签、描述、关联的设置 ID 等等。

继续上面的例子,我们给 my_theme_accent_color 设置添加一个颜色选择器控件:

$wp_customize->add_control(
    new WP_Customize_Color_Control(
        $wp_customize,
        'my_theme_accent_color',
        array(
            'label'    => __( 'Accent Color', 'my-theme' ),
            'section'  => 'colors', // 放到哪个 section 下面
            'settings' => 'my_theme_accent_color', // 关联哪个 setting
        )
    )
);

这段代码干了几件事:

  1. 使用 WP_Customize_Color_Control 类创建一个颜色选择器控件。
  2. 设置控件的 ID 为 my_theme_accent_color (和 setting 的ID一样,可以简化代码理解)。
  3. 设置控件的标签为 "Accent Color"。
  4. 将控件放到名为 colors 的 section 下面(这个 section 稍后会讲到)。
  5. 将控件关联到 my_theme_accent_color 这个 setting。

六、组织界面: 面板和分区的妙用

如果所有的控件都堆在一起,那 Customizer 界面就成了一锅粥。为了让界面更清晰,Customizer API 提供了面板(Panels)和分区(Sections)的概念。

  • 面板(Panels): 就像一个大的文件夹,可以包含多个分区。
  • 分区(Sections): 就像文件夹里的子文件夹,可以包含多个控件。

WP_Customize_Manager 提供了 add_panel()add_section() 方法来添加面板和分区。

/**
 * Adds a customize panel.
 *
 * @since 4.0.0
 *
 * @param string $id   A specific ID of the panel.
 * @param array  $args Panel arguments.
 * @return WP_Customize_Panel|null The panel object, if successfully added. Null on failure.
 */
public function add_panel( $id, $args = array() ) {
    // ... 省略代码 ...
}

/**
 * Adds a customize section.
 *
 * @since 4.0.0
 *
 * @param string $id   A specific ID of the section.
 * @param array  $args Section arguments.
 * @return WP_Customize_Section|null The section object, if successfully added. Null on failure.
 */
public function add_section( $id, $args = array() ) {
    // ... 省略代码 ...
}

参数同样是 ID 和参数数组。

举个例子,我们添加一个名为 "My Theme Options" 的面板,然后在该面板下添加一个名为 "Colors" 的分区:

$wp_customize->add_panel(
    'my_theme_options',
    array(
        'title'    => __( 'My Theme Options', 'my-theme' ),
        'priority' => 10, // 控制面板的显示顺序
    )
);

$wp_customize->add_section(
    'colors',
    array(
        'title'    => __( 'Colors', 'my-theme' ),
        'panel'    => 'my_theme_options', // 放到哪个面板下面
        'priority' => 20, // 控制分区的显示顺序
    )
);

这样,我们就创建了一个面板和一个分区,然后就可以把控件放到这个分区下面了(就像上面添加颜色选择器控件的例子一样)。

七、WP_Customize_Setting:数据的灵魂

WP_Customize_Setting 类代表一个自定义设置。它负责:

  • 存储设置的值。
  • 验证设置的值。
  • 清理设置的值。
  • 保存设置的值到数据库。

WP_Customize_Setting 有几个重要的属性:

  • $id: 设置的 ID。
  • $default: 设置的默认值。
  • $transport: 设置的传输方式(refreshpostMessage)。
  • $type: 设置的类型(比如 theme_mod, option)。
  • $capability: 用户需要什么权限才能修改这个设置。

WP_Customize_Setting 还有几个重要的方法:

  • value(): 获取设置的值。
  • update( $value ): 更新设置的值。
  • validate( $value ): 验证设置的值。
  • sanitize( $value ): 清理设置的值。

八、WP_Customize_Control:交互的桥梁

WP_Customize_Control 类代表一个自定义控件。它负责:

  • 在 Customizer 界面上显示控件。
  • 处理用户的输入。
  • 更新关联的 setting 的值。

WP_Customize_Control 有几个重要的属性:

  • $id: 控件的 ID。
  • $label: 控件的标签。
  • $description: 控件的描述。
  • $section: 控件所属的分区 ID。
  • $settings: 关联的 setting 的 ID。
  • $type: 控件的类型(比如 text, color, select)。

WP_Customize_Control 还有一个重要的方法:

  • render_content(): 渲染控件的内容。 你需要在这个方法里输出 HTML 代码来显示控件。

九、WP_Customize_SectionWP_Customize_Panel:界面的骨架

WP_Customize_SectionWP_Customize_Panel 类分别代表自定义分区和自定义面板。它们的主要作用是组织 Customizer 界面,让用户更容易找到和修改自己想要的设置。

它们都有一些基本的属性,比如:

  • $id: ID。
  • $title: 标题。
  • $description: 描述。
  • $priority: 显示顺序。

十、WP_Customize_Manager 的核心方法:

方法名 功能描述
add_setting() 注册一个新的自定义设置。
add_control() 注册一个新的自定义控件。
add_section() 注册一个新的自定义分区。
add_panel() 注册一个新的自定义面板。
get_setting() 获取一个自定义设置对象。
get_control() 获取一个自定义控件对象。
get_section() 获取一个自定义分区对象。
get_panel() 获取一个自定义面板对象。
remove_setting() 移除一个自定义设置。
remove_control() 移除一个自定义控件。
remove_section() 移除一个自定义分区。
remove_panel() 移除一个自定义面板。
register_control_type() 注册一个新的自定义控件类型。
register_section_type() 注册一个新的自定义分区类型。
register_panel_type() 注册一个新的自定义面板类型。
customize() 获取所有已注册的自定义设置、控件、分区和面板。
is_preview() 判断当前是否是 Customizer 预览模式。
is_theme_active() 判断当前主题是否激活。
save() 保存用户的更改到数据库。
validate_setting_values() 验证所有设置的值。

十一、PostMessage vs Refresh: 实时预览的两种方式

Customizer API 提供了两种实时预览的方式:

  • refresh (默认): 当用户修改一个设置时,整个预览窗口会刷新。 这种方式比较简单,但效率较低,因为每次修改都要重新加载整个页面。

  • postMessage: 当用户修改一个设置时,Customizer 会通过 JavaScript 发送一个消息给预览窗口。 预览窗口收到消息后,会通过 JavaScript 动态更新相应的元素。 这种方式效率较高,但需要编写 JavaScript 代码来处理消息。

选择哪种方式取决于你的需求。如果你的主题比较简单,refresh 方式就足够了。如果你的主题比较复杂,或者你需要更流畅的实时预览体验,那么 postMessage 方式是更好的选择。

十二、实战演练:创建一个简单的 Customizer 设置

让我们来创建一个简单的 Customizer 设置,让用户可以修改网站的背景颜色。

  1. 注册设置:
add_action( 'customize_register', 'my_theme_customize_register' );

function my_theme_customize_register( $wp_customize ) {
    $wp_customize->add_setting(
        'my_theme_background_color',
        array(
            'default'   => '#ffffff',
            'transport' => 'postMessage',
        )
    );
}
  1. 添加控件:
add_action( 'customize_register', 'my_theme_customize_register' );

function my_theme_customize_register( $wp_customize ) {
    $wp_customize->add_setting(
        'my_theme_background_color',
        array(
            'default'   => '#ffffff',
            'transport' => 'postMessage',
        )
    );

    $wp_customize->add_control(
        new WP_Customize_Color_Control(
            $wp_customize,
            'my_theme_background_color',
            array(
                'label'    => __( 'Background Color', 'my-theme' ),
                'section'  => 'colors', // 放到哪个 section 下面
                'settings' => 'my_theme_background_color',
            )
        )
    );
}
  1. 添加分区:
add_action( 'customize_register', 'my_theme_customize_register' );

function my_theme_customize_register( $wp_customize ) {
    $wp_customize->add_section(
        'colors',
        array(
            'title'    => __( 'Colors', 'my-theme' ),
            'priority' => 20,
        )
    );

    $wp_customize->add_setting(
        'my_theme_background_color',
        array(
            'default'   => '#ffffff',
            'transport' => 'postMessage',
        )
    );

    $wp_customize->add_control(
        new WP_Customize_Color_Control(
            $wp_customize,
            'my_theme_background_color',
            array(
                'label'    => __( 'Background Color', 'my-theme' ),
                'section'  => 'colors', // 放到哪个 section 下面
                'settings' => 'my_theme_background_color',
            )
        )
    );
}
  1. 添加 JavaScript 代码,实现实时预览:
add_action( 'customize_preview_init', 'my_theme_customize_preview_js' );

function my_theme_customize_preview_js() {
    wp_enqueue_script(
        'my-theme-customizer',
        get_template_directory_uri() . '/js/customizer.js',
        array( 'customize-preview' ),
        '1.0',
        true
    );
}

js/customizer.js 文件中,添加以下代码:

( function( $ ) {

    wp.customize( 'my_theme_background_color', function( value ) {
        value.bind( function( newval ) {
            $( 'body' ).css( 'background-color', newval );
        } );
    } );

} )( jQuery );
  1. 在主题的 header.php 文件中,添加以下代码:
<style type="text/css">
    body {
        background-color: <?php echo get_theme_mod( 'my_theme_background_color', '#ffffff' ); ?>;
    }
</style>

现在,你就可以在 Customizer 界面中修改网站的背景颜色,并实时预览效果了。

十三、WP_Customize_Manager 的高级用法:

  • 自定义控件类型: 你可以创建自己的控件类型,来满足更复杂的需求。
  • 自定义设置类型: 你可以创建自己的设置类型,来存储更复杂的数据。
  • 使用 JavaScript API: Customizer API 提供了丰富的 JavaScript API,让你可以在客户端进行更灵活的操作。
  • 与其他 API 集成: 你可以将 Customizer API 与其他 API 集成,比如 REST API,来实现更强大的功能。

十四、总结:

WP_Customize_Manager 是 WordPress Customizer API 的核心类,负责管理所有的自定义选项、控件、面板和分区。 掌握 WP_Customize_Manager 的用法,可以让你轻松地创建强大的 Customizer 界面,让用户可以自定义你的主题或插件。

希望今天的讲座对大家有所帮助! 散会!

发表回复

您的邮箱地址不会被公开。 必填项已用 * 标注