剖析 `WP_Customize_Setting` 类的源码,解释它是如何与数据库中的主题选项进行双向绑定的。

咳咳,各位观众老爷,晚上好!欢迎来到今天的“WordPress主题定制内幕”讲座。我是今天的讲师,老司机带你飞~

今天咱们要聊的是WordPress主题定制里一个非常核心的东西:WP_Customize_Setting 类。这玩意儿就像主题选项和数据库之间的一根神奇的线,把它们紧紧地绑在一起,实现了双向绑定。听起来有点抽象?别怕,咱们一步步来,保证你听完之后,也能自己捏一个出来。

一、WP_Customize_Setting 是个啥?

首先,咱们得知道 WP_Customize_Setting 到底是干什么的。简单来说,它是WordPress Customizer(主题定制器)里用来表示一个设置项的类。这个设置项可以是主题颜色、Logo、字体大小等等,任何你想让用户自定义的东西,都可以用它来表示。

更重要的是,它负责:

  • 定义设置项的属性: 比如设置项的ID、类型、默认值、传输方式等等。
  • 与数据库交互: 读取设置项的值,并把用户修改后的值保存到数据库里。
  • 验证和过滤: 对用户输入的值进行验证,确保数据的合法性,并进行过滤,防止恶意代码注入。
  • 实时预览: 把用户修改后的值实时地反映到主题预览中。

可以把它想象成一个中间人,夹在主题选项和数据库之间,负责传递信息,确保一切都井井有条。

二、WP_Customize_Setting 的核心属性

WP_Customize_Setting 类有很多属性,但最核心的几个是:

属性名 类型 描述
$id string 设置项的唯一ID,就像人的身份证号一样。
$transport string 设置项的传输方式,可以是 postMessage(实时预览)或 refresh(刷新页面)。
$capability string 用户需要具备的权限才能修改这个设置项。
$default mixed 设置项的默认值,如果用户没有自定义,就使用这个值。
$type string 设置项的类型,可以是 theme_mod(主题选项)或 option(普通选项)。 theme_mod 会存储在 wp_options 表中,键名为 theme_mods_{主题名},而 option 则是直接存储在 wp_options 表中,键名为 $id
$sanitize_callback callable 用于清理和验证用户输入的回调函数。
$validate_callback callable 用于验证用户输入的回调函数(在sanitization之前执行)。
$dirty boolean 标记设置是否已更改。 自定义器在初始化时会设置为 false,当设置值被更改时,会设置为 true。 这对于判断是否需要执行某些操作非常有用,例如在保存设置之前执行某些清理工作。

这些属性决定了 WP_Customize_Setting 的行为,咱们后面会详细讲解。

三、WP_Customize_Setting 是如何工作的?(源码剖析)

现在咱们来深入源码,看看 WP_Customize_Setting 是如何实现双向绑定的。

  1. 实例化 WP_Customize_Setting

首先,你需要在 Customizer 里注册一个 WP_Customize_Setting 实例。比如:

<?php
add_action( 'customize_register', 'my_theme_customize_register' );
function my_theme_customize_register( $wp_customize ) {

  $wp_customize->add_setting(
    'my_theme_primary_color',
    array(
      'default'           => '#007bff',
      'transport'         => 'postMessage',
      'sanitize_callback' => 'sanitize_hex_color',
    )
  );

  $wp_customize->add_control(
    new WP_Customize_Color_Control(
      $wp_customize,
      'my_theme_primary_color',
      array(
        'label'    => __( 'Primary Color', 'my-theme' ),
        'section'  => 'colors',
        'settings' => 'my_theme_primary_color',
      )
    )
  );
}
?>

这段代码做了几件事:

  • add_action( 'customize_register', 'my_theme_customize_register' ):在 Customizer 初始化时,执行 my_theme_customize_register 函数。
  • $wp_customize->add_setting( 'my_theme_primary_color', ... ):注册一个名为 my_theme_primary_color 的设置项。
    • default:设置默认值为 #007bff
    • transport:设置传输方式为 postMessage(实时预览)。
    • sanitize_callback:设置清理回调函数为 sanitize_hex_color(确保用户输入的是合法的十六进制颜色值)。
  • $wp_customize->add_control( new WP_Customize_Color_Control( ... ) ):添加一个颜色选择控件,让用户可以修改这个设置项的值。

add_setting() 内部会创建一个 WP_Customize_Setting 对象,并把它添加到 $wp_customize 对象的 $settings 属性中。

  1. 从数据库读取值

当 Customizer 加载时,WP_Customize_Setting 会从数据库读取设置项的值。这个过程通常发生在 WP_Customize_Setting::value() 方法中。

<?php
/**
 * Get the current value of the setting.
 *
 * @return mixed The setting value.
 */
public function value() {
  if ( isset( $this->value ) ) {
    return $this->value;
  }

  $this->value = $this->default; // Start with the default.

  if ( 'theme_mod' === $this->type ) {
    $theme_mod_value = get_theme_mod( $this->id );
    if ( false !== $theme_mod_value ) {
      $this->value = $theme_mod_value;
    }
  } elseif ( 'option' === $this->type ) {
    $option_value = get_option( $this->id );
    if ( false !== $option_value ) {
      $this->value = $option_value;
    }
  }

  /**
   * Filters the return value of WP_Customize_Setting::value().
   *
   * @since 4.2.0
   *
   * @param mixed                $value  The setting value.
   * @param WP_Customize_Setting $this   WP_Customize_Setting instance.
   */
  $this->value = apply_filters( 'customize_value_' . $this->id, $this->value, $this );

  return $this->value;
}
?>

这个方法做了几件事:

  • 首先,检查 $this->value 是否已经存在,如果存在,直接返回。这是为了避免重复读取数据库。
  • 如果 $this->value 不存在,就把它初始化为 $this->default(默认值)。
  • 然后,根据 $this->type 的值,从数据库读取设置项的值:
    • 如果 $this->typetheme_mod,就调用 get_theme_mod( $this->id )wp_options 表中读取 theme_mods_{主题名} 选项的值。
    • 如果 $this->typeoption,就调用 get_option( $this->id )wp_options 表中读取 $this->id 选项的值。
  • 最后,应用一个过滤器 customize_value_{$this->id},允许其他代码修改设置项的值。
  1. 用户修改值

当用户在 Customizer 里修改设置项的值时,Customizer 会通过 AJAX 请求把新的值发送到服务器。服务器端的 WP_Customize_Setting::sanitize() 方法会被调用,对新的值进行清理和验证。

<?php
/**
 * Sanitize a value.
 *
 * @param mixed $value Raw value.
 * @return mixed Sanitized value.
 */
public function sanitize( $value ) {
  if ( is_callable( $this->sanitize_callback ) ) {
    $value = call_user_func( $this->sanitize_callback, $value, $this );
  }
  return $value;
}
?>

这个方法很简单,就是判断 $this->sanitize_callback 是否是一个可调用的函数,如果是,就调用它来清理和验证 $value

  1. 保存到数据库

如果清理和验证通过,Customizer 会调用 WP_Customize_Setting::update() 方法把新的值保存到数据库。

<?php
/**
 * Update the setting's value.
 *
 * @since 4.2.0
 *
 * @param mixed $value The value to update.
 * @return bool Whether the value was updated.
 */
public function update( $value ) {
  $value = $this->sanitize( $value );

  if ( 'theme_mod' === $this->type ) {
    $success = set_theme_mod( $this->id, $value );
  } elseif ( 'option' === $this->type ) {
    $success = update_option( $this->id, $value );
  } else {
    $success = false;
  }

  if ( $success ) {
    $this->value = $value;
    $this->dirty = true; // Mark the setting as dirty.
    $this->manager->saved_changes = true; // Mark that there are changes to save.
    $this->manager->trigger( 'customize_save_' . $this->id, $this );

    /**
     * Fires after a customize setting has been updated.
     *
     * @since 4.2.0
     *
     * @param WP_Customize_Setting $this WP_Customize_Setting instance.
     */
    do_action( 'customize_update_' . $this->id, $this );
  }

  return $success;
}
?>

这个方法做了几件事:

  • 首先,调用 WP_Customize_Setting::sanitize()$value 进行清理和验证。
  • 然后,根据 $this->type 的值,把新的值保存到数据库:
    • 如果 $this->typetheme_mod,就调用 set_theme_mod( $this->id, $value ) 把值保存到 wp_options 表中,键名为 theme_mods_{主题名}
    • 如果 $this->typeoption,就调用 update_option( $this->id, $value ) 把值保存到 wp_options 表中,键名为 $this->id
  • 如果保存成功,就更新 $this->value 的值,并触发 customize_save_{$this->id}customize_update_{$this->id} 两个 action。
  • $this->dirty 设置为 true,表示此设置项已被修改。
  • $this->manager->saved_changes 设置为 true,表示有更改需要保存。
  1. 实时预览

如果 $this->transport 的值是 postMessage,Customizer 会通过 JavaScript 把新的值发送到主题预览页面,实现实时预览。这个过程涉及到 WP_Customize_Control 和 JavaScript API,咱们这里就不深入讲解了。

四、双向绑定的奥秘

现在咱们来总结一下 WP_Customize_Setting 是如何实现双向绑定的:

  • 读取: 当 Customizer 加载时,WP_Customize_Setting 从数据库读取设置项的值,并把它存储在 $this->value 属性中。
  • 修改: 当用户在 Customizer 里修改设置项的值时,Customizer 会把新的值发送到服务器,WP_Customize_Setting::sanitize() 方法会被调用,对新的值进行清理和验证。
  • 保存: 如果清理和验证通过,WP_Customize_Setting::update() 方法会把新的值保存到数据库,并更新 $this->value 属性。
  • 预览: 如果 $this->transport 的值是 postMessage,Customizer 会通过 JavaScript 把新的值发送到主题预览页面,实现实时预览。

通过这些步骤,WP_Customize_Setting 把主题选项和数据库紧紧地绑在一起,实现了双向绑定。无论用户在 Customizer 里修改设置项的值,还是直接修改数据库里的值,都能保证两者的同步。

五、WP_Customize_Setting 的应用场景

WP_Customize_Setting 可以应用到各种各样的场景中,比如:

  • 主题颜色: 让用户自定义主题的颜色,包括背景色、文字颜色、链接颜色等等。
  • Logo: 让用户上传自己的 Logo。
  • 字体: 让用户选择自己喜欢的字体。
  • 布局: 让用户选择不同的布局,比如单栏布局、双栏布局、三栏布局等等。
  • 社交媒体链接: 让用户添加自己的社交媒体链接。
  • 自定义CSS: 让用户添加自己的 CSS 代码。

只要你想让用户自定义的东西,都可以用 WP_Customize_Setting 来实现。

六、自定义 WP_Customize_Setting

有时候,WordPress 提供的 WP_Customize_Setting 可能不能满足你的需求,你需要自定义一个 WP_Customize_Setting 类。

自定义 WP_Customize_Setting 类很简单,只需要继承 WP_Customize_Setting 类,并重写你想要修改的方法即可。

比如,你可以自定义一个 WP_Customize_Range_Setting 类,让用户可以输入一个范围内的数字。

<?php
class WP_Customize_Range_Setting extends WP_Customize_Setting {

  public $type = 'range';

  public function __construct( $manager, $id, $args = array() ) {
    parent::__construct( $manager, $id, $args );

    // Set default value if not set.
    if ( ! isset( $this->default ) ) {
      $this->default = 0;
    }

    // Set transport to refresh if not set.
    if ( ! isset( $this->transport ) ) {
      $this->transport = 'refresh';
    }
  }

  public function sanitize( $value ) {
    $value = intval( $value ); // Convert to integer.
    $value = max( $this->min, min( $this->max, $value ) ); // Limit to range.
    return $value;
  }
}
?>

然后,你就可以在 Customizer 里使用这个自定义的 WP_Customize_Setting 类了。

七、总结

今天咱们深入剖析了 WP_Customize_Setting 类的源码,讲解了它是如何与数据库中的主题选项进行双向绑定的。希望通过今天的讲座,你对 WP_Customize_Setting 类有了更深入的理解,也能自己灵活运用它,打造出更加强大的 WordPress 主题定制功能。

记住,WP_Customize_Setting 就像一根神奇的线,把主题选项和数据库紧紧地绑在一起,实现了双向绑定。掌握了它,你就掌握了 WordPress 主题定制的钥匙。

好了,今天的讲座就到这里,感谢大家的观看!如果有什么问题,欢迎在评论区留言。下次再见!

发表回复

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