WordPress函数:add_option 添加设置选项

编辑文章

简介

add_option 函数用于在WordPress选项表中创建并存储一个新的设置项,常用于保存插件、主题的配置信息。它是WordPress持久化存储简单数据(如开关状态、文本参数)最核心的工具之一。

语法

add_option( string $option, mixed $value = '', string $deprecated = '', string|bool $autoload = 'yes' )

核心文件: wp-includes/option.php。该函数内部会调用 wp_protect_special_option 进行关键选项名检查,并最终通过 $wpdb 类执行SQL INSERT 操作。

参数与返回值说明:

参数 类型 默认值 说明
$option 字符串 (必填) 要创建的选项名称。建议使用小写字母、数字和下划线,并确保唯一性。
$value 混合 '' 要存储的选项值。可以是字符串、数组、数字、对象(需可序列化)。
$deprecated 字符串 '' 已弃用。历史上用于描述,现已不再使用,传递任何值均无效。
$autoload 字符串/布尔 'yes' 是否在WordPress所有页面加载时自动从数据库载入该选项。设为 'no' 可提升性能,适用于不常用的后台选项。
返回值 布尔 成功添加返回 true。若选项已存在,则返回 false

用法

基础用法

在插件或主题的初始化函数中,存储一个简单的设置值。这是最常见的场景,例如设置一个首次安装的标记。

// 在插件主文件或主题的 functions.php 中添加
function myplugin_setup_default_options() {
    // 如果选项 'myplugin_first_install' 不存在,则创建它
    if ( false === get_option( 'myplugin_first_install' ) ) {
        add_option( 'myplugin_first_install', date( 'Y-m-d H:i:s' ) );
    }
}
// 在适当的钩子上运行,例如插件激活时或 `init` 动作
add_action( 'init', 'myplugin_setup_default_options' );

为什么先检查 get_option 因为 add_option 在选项已存在时会直接返回 false 且不修改原值。这种“只添加一次”的逻辑确保了默认设置不会被意外覆盖。

进阶用法

存储结构化数据(如数组)并管理自动加载行为,适用于包含多个子项的复杂配置。

// 存储一个包含多个设置的关联数组,并禁止自动加载
function mytheme_save_complex_settings() {
    $complex_settings = array(
        'layout'           => 'sidebar-right',
        'custom_css'       => 'body { color: #333; }',
        'featured_enabled' => true,
        'api_key'          => '', // 用户稍后填写
    );

    // 注意:我们传递了 $autoload='no',因为该配置可能只在后台设置页面使用
    add_option( 'mytheme_design_config', $complex_settings, '', 'no' );
}
// 假设在主题切换时运行此函数
add_action( 'after_switch_theme', 'mytheme_save_complex_settings' );

// 如何读取这个选项?使用 get_option,它自动反序列化数组。
$settings = get_option( 'mytheme_design_config' );
if ( $settings && isset( $settings['layout'] ) ) {
    // 在模板中使用时,务必对输出进行转义
    echo '布局模式:' . esc_html( $settings['layout'] );
}

易错点

  • 覆盖已有选项
    直接调用 add_option( 'existing_option', 'new_value' ) 不会更新已存在的选项。若需“添加或更新”,应使用 update_option 函数。add_option 应仅在初始化默认值时使用。

  • 存储非标量数据时的序列化陷阱
    add_option 会自动对数组、对象等非标量数据进行序列化后存储。但如果你存储一个已序列化的字符串,它会被再次序列化,导致取出时得到混乱的数据。确保 $value 参数总是传递原始数据结构,而非序列化后的字符串。

  • 选项名冲突
    使用过于通用的选项名(如 version, settings)极易与其他插件或主题冲突。始终为选项名添加唯一前缀,例如 myplugin_mytheme_

  • 忽视自动加载对性能的影响
    将所有选项的 $autoload 都设为 'yes'(默认),会导致 wp_load_alloptions() 函数一次性加载大量不常用的数据到内存,拖慢每个页面。请仅为高频使用的核心选项开启自动加载。

  • 未考虑多站点环境
    在WordPress多站点(Multisite)网络中,add_option 操作的是当前站点的选项表(如 wp_2_options)。如果需要添加网络级别的选项,应使用 add_site_option 函数。

最佳实践

性能优化:精确控制自动加载

将选项分为“高频”与“低频”使用两类。首页、文章页等几乎每个页面都需要的核心设置(如主题名称、基础开关)可设为自动加载。而仅在后台上某个设置页面使用的详细配置,应设为 autoload='no'

// 高频选项:自动加载
add_option( 'myplugin_core_feature_enabled', true, '', 'yes' );

// 低频选项:不自动加载
add_option( 'myplugin_debug_log_history', array(), '', 'no' );

代码可维护性:集中管理选项名

在大型项目中,分散在各处的选项名字符串是“魔法数字”的一种,难以维护和查找。定义一个类或常量来集中管理所有选项名。

// 在插件的主类或专用配置文件中定义
class MyPlugin_Config {
    const OPTION_INSTALL_DATE = 'myplugin_install_date';
    const OPTION_USER_SETTINGS = 'myplugin_user_settings';
    const OPTION_ADVANCED_FLAGS = 'myplugin_advanced_flags';
}

// 使用时
add_option( MyPlugin_Config::OPTION_INSTALL_DATE, current_time( 'mysql' ) );
$settings = get_option( MyPlugin_Config::OPTION_USER_SETTINGS );

安全性增强:处理用户输入

虽然 add_option 本身会将值安全地存入数据库,但如果存储的值来源于用户输入(如表单提交),必须在存储前进行严格的验证和清理,以防止存储恶意代码。并且在输出时必须再次转义。

// 假设接收来自表单的输入
$user_input_text = $_POST['custom_message'] ?? ''; // 不安全!

// 在存储前进行清理(根据数据类型选择合适的函数)
$clean_value = sanitize_textarea_field( $user_input_text ); // 清理文本区域内容

// 现在可以安全地存储
update_option( 'myplugin_user_message', $clean_value ); // 此处用update_option,因为可能已存在

// --- 在模板中输出时 ---
$stored_message = get_option( 'myplugin_user_message' );
// 必须根据输出上下文进行转义
echo '<p>' . esc_textarea( $stored_message ) . '</p>'; // 如果回填到textarea
// 或
echo '<div>' . wp_kses_post( $stored_message ) . '</div>'; // 如果允许少量HTML

与现代开发模式结合:为REST API准备

如果你在开发支持WordPress REST API的主题或插件,可以考虑将选项通过 register_rest_route 暴露为API端点。此时,使用 get_option 读取并通过API返回时,应确保数据结构清晰(如JSON友好),并考虑权限检查(permission_callback)。

add_action( 'rest_api_init', function () {
    register_rest_route( 'myplugin/v1', '/settings', array(
        'methods'  => 'GET',
        'callback' => function () {
            // 获取所有相关选项,组装成一个对象
            $data = array(
                'design' => get_option( 'myplugin_design_config', array() ),
                'flags'  => get_option( 'myplugin_feature_flags', array() ),
            );
            // 直接返回,WP REST API会自动处理JSON序列化
            return $data;
        },
        'permission_callback' => function () {
            // 重要:进行权限检查,例如只允许管理员访问
            return current_user_can( 'manage_options' );
        }
    ) );
} );