分析 `add_option()` 和 `delete_option()` 函数的源码,它们如何与 `wp_options` 表进行交互?

嘿,各位代码爱好者,大家好!今天咱们来聊聊 WordPress 里两个非常重要,但又常常被我们忽略的小家伙:add_option()delete_option()。别看它们名字简单,但它们可是直接操纵 WordPress 核心数据库表 wp_options 的幕后英雄。接下来,咱们就一起扒一扒它们的源码,看看它们是怎么跟 wp_options 表眉来眼去的。

一、wp_options 表:WordPress 的记忆中枢

在深入函数之前,我们先来了解一下 wp_options 表。你可以把它想象成 WordPress 的大脑,负责存储各种各样的设置和数据,比如:

  • 网站标题和描述
  • 主题设置
  • 插件设置
  • 缓存数据
  • 等等等等…

这个表结构比较简单,关键字段如下:

字段名 数据类型 描述
option_id BIGINT(20) 自增主键,每一行记录的唯一标识。
option_name VARCHAR(191) 选项名称,也就是我们常说的 Option Key。这是唯一索引,保证选项名称的唯一性。
option_value LONGTEXT 选项的值,可以存储任何类型的数据,比如字符串、数组、对象等。WordPress 会自动进行序列化和反序列化。
autoload VARCHAR(20) 用于指定是否在 WordPress 初始化时自动加载该选项。可选值为 ‘yes’ 或 ‘no’。’yes’ 表示自动加载,’no’ 表示不自动加载。自动加载可以提高性能,但会增加内存消耗。

autoload 字段非常重要,它决定了 WordPress 在启动时是否会自动加载这个选项。如果一个选项经常被用到,设置为 yes 可以提高性能;反之,设置为 no 可以减少内存占用。

二、add_option():把东西存进大脑

add_option() 函数的作用就是在 wp_options 表中添加一条新的记录,也就是往 WordPress 的“大脑”里存入一些新的信息。咱们来看看它的源码(简化版,去掉了部分错误处理和钩子):

function add_option( $option, $value = '', $deprecated = '', $autoload = 'yes' ) {
    global $wpdb;

    // 1. 检查选项名称是否合法
    if ( ! is_scalar( $option ) ) {
        return false;
    }

    $option = trim( $option );
    if ( empty( $option ) ) {
        return false;
    }

    // 2. 检查选项是否已经存在
    if ( get_option( $option ) !== false ) {
        return false;
    }

    // 3. 数据序列化
    $value = maybe_serialize( $value );

    // 4. 构建 SQL 语句
    $autoload = ( 'no' === $autoload ) ? 'no' : 'yes';
    $sql = $wpdb->prepare(
        "INSERT INTO `$wpdb->options` (`option_name`, `option_value`, `autoload`) VALUES (%s, %s, %s)",
        $option,
        $value,
        $autoload
    );

    // 5. 执行 SQL 语句
    $result = $wpdb->query( $sql );

    // 6. 触发钩子
    if ( $result ) {
        wp_cache_delete( 'alloptions', 'options' ); // 清理缓存
        do_action( 'add_option', $option, $value );
        return true;
    }

    return false;
}

让我们一步步来解读这个函数:

  1. 参数校验: 首先,它会检查传入的选项名称 $option 是否合法,必须是标量类型(比如字符串、数字等),并且不能为空。

  2. 检查是否存在: 接下来,它会用 get_option() 函数检查该选项是否已经存在。如果存在,则直接返回 false,避免重复添加。

  3. 数据序列化: 如果选项值 $value 不是字符串类型,它会使用 maybe_serialize() 函数将其序列化成字符串,以便存储到数据库中。 这是因为 wp_options 表的 option_value 字段是 TEXT 类型,只能存储字符串。

  4. 构建 SQL 语句: 它会根据传入的参数构建一条 INSERT SQL 语句,用于向 wp_options 表中插入一条新的记录。$wpdb->prepare() 函数可以防止 SQL 注入攻击。

  5. 执行 SQL 语句: 它会使用 $wpdb->query() 函数执行 SQL 语句,将数据插入到 wp_options 表中。

  6. 触发钩子: 如果插入成功,它会清理缓存、触发 add_option 钩子,并返回 true

举个栗子:

add_option( 'my_plugin_setting', array( 'color' => 'red', 'size' => 'large' ), '', 'yes' );

这条代码会在 wp_options 表中添加一条记录,option_namemy_plugin_settingoption_value 为序列化后的数组 a:2:{s:5:"color";s:3:"red";s:4:"size";s:5:"large";}autoloadyes

三、delete_option():把东西从大脑里删除

delete_option() 函数的作用是从 wp_options 表中删除一条记录,也就是从 WordPress 的“大脑”里删除一些信息。咱们来看看它的源码(同样是简化版):

function delete_option( $option ) {
    global $wpdb;

    // 1. 检查选项名称是否合法
    if ( ! is_scalar( $option ) ) {
        return false;
    }

    $option = trim( $option );
    if ( empty( $option ) ) {
        return false;
    }

    // 2. 构建 SQL 语句
    $sql = $wpdb->prepare( "DELETE FROM `$wpdb->options` WHERE `option_name` = %s", $option );

    // 3. 执行 SQL 语句
    $result = $wpdb->query( $sql );

    // 4. 触发钩子
    if ( $result ) {
        wp_cache_delete( 'alloptions', 'options' ); // 清理缓存
        do_action( 'delete_option', $option );
        return true;
    }

    return false;
}

这个函数比 add_option() 简单多了:

  1. 参数校验: 同样,它会检查传入的选项名称 $option 是否合法,必须是标量类型,并且不能为空。

  2. 构建 SQL 语句: 它会构建一条 DELETE SQL 语句,用于从 wp_options 表中删除 option_name 等于 $option 的记录。

  3. 执行 SQL 语句: 它会使用 $wpdb->query() 函数执行 SQL 语句,将数据从 wp_options 表中删除。

  4. 触发钩子: 如果删除成功,它会清理缓存、触发 delete_option 钩子,并返回 true

举个栗子:

delete_option( 'my_plugin_setting' );

这条代码会从 wp_options 表中删除 option_namemy_plugin_setting 的记录。

四、add_option()delete_option() 的注意事项

  • 选项名称的唯一性: option_name 必须是唯一的,不能重复。如果你尝试添加一个已经存在的选项,add_option() 函数会返回 false
  • 数据类型: option_value 可以存储任何类型的数据,但 WordPress 会自动进行序列化和反序列化。因此,你不需要手动进行序列化和反序列化操作。
  • autoload 的使用: autoload 字段决定了是否在 WordPress 初始化时自动加载该选项。如果一个选项经常被用到,设置为 yes 可以提高性能;反之,设置为 no 可以减少内存占用。合理设置 autoload 可以优化 WordPress 的性能。
  • 谨慎使用: wp_options 表是 WordPress 的核心数据表,存储着大量的配置信息。因此,在使用 add_option()delete_option() 函数时要格外小心,避免误操作导致数据丢失或网站崩溃。
  • 插件卸载: 当你的插件被卸载时,一定要记得使用 delete_option() 函数删除插件相关的选项,避免在数据库中留下垃圾数据。
  • 缓存: WordPress 有缓存机制,所以在修改 wp_options 表后,需要清理缓存才能使修改生效。add_option()delete_option() 函数会自动清理缓存,但如果你直接操作数据库,就需要手动清理缓存。

五、实战演练:一个简单的插件设置

假设我们要开发一个简单的插件,允许用户自定义网站的背景颜色。我们可以使用 add_option()get_option() 函数来实现这个功能。

  1. 插件激活时添加选项:
function my_plugin_activate() {
    add_option( 'my_plugin_background_color', '#ffffff', '', 'yes' );
}
register_activation_hook( __FILE__, 'my_plugin_activate' );

这段代码会在插件激活时,向 wp_options 表中添加一个名为 my_plugin_background_color 的选项,默认值为白色 (#ffffff),并设置为自动加载。

  1. 插件卸载时删除选项:
function my_plugin_deactivate() {
    delete_option( 'my_plugin_background_color' );
}
register_deactivation_hook( __FILE__, 'my_plugin_deactivate' );

这段代码会在插件卸载时,从 wp_options 表中删除 my_plugin_background_color 选项。

  1. 在后台添加设置页面:
function my_plugin_menu() {
    add_options_page(
        'My Plugin Settings',
        'My Plugin',
        'manage_options',
        'my-plugin-settings',
        'my_plugin_settings_page'
    );
}
add_action( 'admin_menu', 'my_plugin_menu' );

function my_plugin_settings_page() {
    ?>
    <div class="wrap">
        <h1>My Plugin Settings</h1>
        <form method="post" action="options.php">
            <?php
            settings_fields( 'my_plugin_settings' );
            do_settings_sections( 'my-plugin-settings' );
            submit_button();
            ?>
        </form>
    </div>
    <?php
}

function my_plugin_register_settings() {
    register_setting( 'my_plugin_settings', 'my_plugin_background_color' );
    add_settings_section(
        'my_plugin_section',
        'Background Color',
        '',
        'my-plugin-settings'
    );
    add_settings_field(
        'my_plugin_background_color',
        'Background Color',
        'my_plugin_background_color_field',
        'my-plugin-settings',
        'my_plugin_section'
    );
}
add_action( 'admin_init', 'my_plugin_register_settings' );

function my_plugin_background_color_field() {
    $color = get_option( 'my_plugin_background_color', '#ffffff' );
    ?>
    <input type="color" name="my_plugin_background_color" value="<?php echo esc_attr( $color ); ?>">
    <?php
}

这段代码会在 WordPress 后台添加一个设置页面,允许用户选择背景颜色。get_option() 函数用于获取当前背景颜色的值,并将其显示在颜色选择器中。

  1. 在前台应用设置:
function my_plugin_add_style() {
    $color = get_option( 'my_plugin_background_color', '#ffffff' );
    ?>
    <style type="text/css">
        body {
            background-color: <?php echo esc_attr( $color ); ?>;
        }
    </style>
    <?php
}
add_action( 'wp_head', 'my_plugin_add_style' );

这段代码会在 WordPress 前台的 <head> 标签中添加一段 CSS 代码,将网站的背景颜色设置为用户在后台设置的颜色。同样,get_option() 函数用于获取当前背景颜色的值。

通过这个简单的例子,我们可以看到 add_option()delete_option() 函数在插件开发中的实际应用。它们是存储和删除插件设置的关键工具。

六、总结

add_option()delete_option() 函数是 WordPress 插件和主题开发中非常常用的函数,它们直接与 wp_options 表进行交互,用于存储和删除配置信息。理解它们的源码和使用方法,可以帮助我们更好地开发 WordPress 插件和主题,并优化 WordPress 的性能。希望今天的讲解能帮助你更深入地了解这两个小而强大的函数,下次再遇到它们,就能胸有成竹,轻松驾驭啦!

好啦,今天的“源码漫游记”就到这里,希望大家有所收获! 咱们下次再见!

发表回复

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