函数文档

update_option()

💡 云策文档标注

概述

update_option() 是 WordPress 核心函数,用于更新已存在的选项值。如果选项不存在,它会自动创建。该函数处理值的序列化和缓存更新,并支持 autoload 参数控制选项加载行为。

关键要点

  • 函数签名:update_option( $option, $value, $autoload = null ),返回布尔值表示更新是否成功。
  • 参数说明:$option 为选项名称(字符串,无需 SQL 转义),$value 为选项值(可序列化,非标量需可序列化),$autoload 控制是否在 WordPress 启动时加载(布尔值或 null,默认 null)。
  • 功能特性:自动序列化值,无需手动调用 serialize();如果新值与旧值相同,返回 false 且不更新;支持通过 Hook(如 pre_update_option)过滤值。
  • 安全建议:插件开发者应在更新选项前检查当前用户权限,例如使用 current_user_can()。
  • 性能注意:autoload 参数影响性能,频繁使用的选项建议设为 true,特定 URL 访问的选项建议设为 false。
  • 兼容性:autoload 值 'yes' 和 'no' 已弃用,推荐使用布尔值 true/false。

代码示例

// 更新核心选项,如设置默认评论状态为关闭
update_option( 'default_comment_status', 'closed' );

// 更新自定义选项,自动创建选项(如果不存在)
update_option( 'my_custom_option', 255 );

// 更新选项并设置 autoload 为 false(不自动加载)
if ( false === get_option( 'my_option' ) ) {
    add_option( 'my_option', 'default_value', '', false );
} else {
    update_option( 'my_option', 'new_value' );
}

注意事项

  • 布尔值 false 作为选项值可能导致与选项不存在的混淆,建议使用整数 0/1 替代或仔细处理检查逻辑。
  • 避免传递 null 作为 $value,可能引发潜在错误;使用 false、0 或空字符串代替。
  • 选项值被缓存,外部修改后需清理缓存(如使用 wp_cache_delete())以确保 update_option() 正常工作。
  • 返回 false 可能表示更新失败、值未变化或选项不存在,需根据上下文判断。

📄 原文内容

Updates the value of an option that was already added.

Description

You do not need to serialize values. If the value needs to be serialized, then it will be serialized before it is inserted into the database.
Remember, resources cannot be serialized or added as an option.

If the option does not exist, it will be created.

This function is designed to work with or without a logged-in user. In terms of security, plugin developers should check the current user’s capabilities before updating any options.

Parameters

$optionstringrequired
Name of the option to update. Expected to not be SQL-escaped.
$valuemixedrequired
Option value. Must be serializable if non-scalar. Expected to not be SQL-escaped.
$autoloadbool|nulloptional
Whether to load the option when WordPress starts up.
Accepts a boolean, or null to stick with the initial value or, if no initial value is set, to leave the decision up to default heuristics in WordPress.
For existing options, $autoload can only be updated using update_option() if $value is also changed.
For backward compatibility 'yes' and 'no' are also accepted, though using these values is deprecated.
Autoloading too many options can lead to performance problems, especially if the options are not frequently used. For options which are accessed across several places in the frontend, it is recommended to autoload them, by using true.
For options which are accessed only on few specific URLs, it is recommended to not autoload them, by using false.
For non-existent options, the default is null, which means WordPress will determine the autoload value.

Default:null

Return

bool True if the value was updated, false otherwise.

Source

function update_option( $option, $value, $autoload = null ) {
	global $wpdb;

	if ( is_scalar( $option ) ) {
		$option = trim( $option );
	}

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

	/*
	 * Until a proper _deprecated_option() function can be introduced,
	 * redirect requests to deprecated keys to the new, correct ones.
	 */
	$deprecated_keys = array(
		'blacklist_keys'    => 'disallowed_keys',
		'comment_whitelist' => 'comment_previously_approved',
	);

	if ( isset( $deprecated_keys[ $option ] ) && ! wp_installing() ) {
		_deprecated_argument(
			__FUNCTION__,
			'5.5.0',
			sprintf(
				/* translators: 1: Deprecated option key, 2: New option key. */
				__( 'The "%1$s" option key has been renamed to "%2$s".' ),
				$option,
				$deprecated_keys[ $option ]
			)
		);
		return update_option( $deprecated_keys[ $option ], $value, $autoload );
	}

	wp_protect_special_option( $option );

	if ( is_object( $value ) ) {
		$value = clone $value;
	}

	$value     = sanitize_option( $option, $value );
	$old_value = get_option( $option );

	/**
	 * Filters a specific option before its value is (maybe) serialized and updated.
	 *
	 * The dynamic portion of the hook name, `$option`, refers to the option name.
	 *
	 * @since 2.6.0
	 * @since 4.4.0 The `$option` parameter was added.
	 *
	 * @param mixed  $value     The new, unserialized option value.
	 * @param mixed  $old_value The old option value.
	 * @param string $option    Option name.
	 */
	$value = apply_filters( "pre_update_option_{$option}", $value, $old_value, $option );

	/**
	 * Filters an option before its value is (maybe) serialized and updated.
	 *
	 * @since 3.9.0
	 *
	 * @param mixed  $value     The new, unserialized option value.
	 * @param string $option    Name of the option.
	 * @param mixed  $old_value The old option value.
	 */
	$value = apply_filters( 'pre_update_option', $value, $option, $old_value );

	/*
	 * If the new and old values are the same, no need to update.
	 *
	 * Unserialized values will be adequate in most cases. If the unserialized
	 * data differs, the (maybe) serialized data is checked to avoid
	 * unnecessary database calls for otherwise identical object instances.
	 *
	 * See https://core.trac.wordpress.org/ticket/38903
	 */
	if ( $value === $old_value || maybe_serialize( $value ) === maybe_serialize( $old_value ) ) {
		return false;
	}

	/** This filter is documented in wp-includes/option.php */
	if ( apply_filters( "default_option_{$option}", false, $option, false ) === $old_value ) {
		return add_option( $option, $value, '', $autoload );
	}

	$serialized_value = maybe_serialize( $value );

	/**
	 * Fires immediately before an option value is updated.
	 *
	 * @since 2.9.0
	 *
	 * @param string $option    Name of the option to update.
	 * @param mixed  $old_value The old option value.
	 * @param mixed  $value     The new option value.
	 */
	do_action( 'update_option', $option, $old_value, $value );

	$update_args = array(
		'option_value' => $serialized_value,
	);

	if ( null !== $autoload ) {
		$update_args['autoload'] = wp_determine_option_autoload_value( $option, $value, $serialized_value, $autoload );
	} else {
		// Retrieve the current autoload value to reevaluate it in case it was set automatically.
		$raw_autoload = $wpdb->get_var( $wpdb->prepare( "SELECT autoload FROM $wpdb->options WHERE option_name = %s LIMIT 1", $option ) );
		$allow_values = array( 'auto-on', 'auto-off', 'auto' );
		if ( in_array( $raw_autoload, $allow_values, true ) ) {
			$autoload = wp_determine_option_autoload_value( $option, $value, $serialized_value, $autoload );
			if ( $autoload !== $raw_autoload ) {
				$update_args['autoload'] = $autoload;
			}
		}
	}

	$result = $wpdb->update( $wpdb->options, $update_args, array( 'option_name' => $option ) );
	if ( ! $result ) {
		return false;
	}

	$notoptions = wp_cache_get( 'notoptions', 'options' );

	if ( is_array( $notoptions ) && isset( $notoptions[ $option ] ) ) {
		unset( $notoptions[ $option ] );
		wp_cache_set( 'notoptions', $notoptions, 'options' );
	}

	if ( ! wp_installing() ) {
		if ( ! isset( $update_args['autoload'] ) ) {
			// Update the cached value based on where it is currently cached.
			$alloptions = wp_load_alloptions( true );

			if ( isset( $alloptions[ $option ] ) ) {
				$alloptions[ $option ] = $serialized_value;
				wp_cache_set( 'alloptions', $alloptions, 'options' );
			} else {
				wp_cache_set( $option, $serialized_value, 'options' );
			}
		} elseif ( in_array( $update_args['autoload'], wp_autoload_values_to_autoload(), true ) ) {
			// Delete the individual cache, then set in alloptions cache.
			wp_cache_delete( $option, 'options' );

			$alloptions = wp_load_alloptions( true );

			$alloptions[ $option ] = $serialized_value;
			wp_cache_set( 'alloptions', $alloptions, 'options' );
		} else {
			// Delete the alloptions cache, then set the individual cache.
			$alloptions = wp_load_alloptions( true );

			if ( isset( $alloptions[ $option ] ) ) {
				unset( $alloptions[ $option ] );
				wp_cache_set( 'alloptions', $alloptions, 'options' );
			}

			wp_cache_set( $option, $serialized_value, 'options' );
		}
	}

	/**
	 * Fires after the value of a specific option has been successfully updated.
	 *
	 * The dynamic portion of the hook name, `$option`, refers to the option name.
	 *
	 * @since 2.0.1
	 * @since 4.4.0 The `$option` parameter was added.
	 *
	 * @param mixed  $old_value The old option value.
	 * @param mixed  $value     The new option value.
	 * @param string $option    Option name.
	 */
	do_action( "update_option_{$option}", $old_value, $value, $option );

	/**
	 * Fires after the value of an option has been successfully updated.
	 *
	 * @since 2.9.0
	 *
	 * @param string $option    Name of the updated option.
	 * @param mixed  $old_value The old option value.
	 * @param mixed  $value     The new option value.
	 */
	do_action( 'updated_option', $option, $old_value, $value );

	return true;
}

Hooks

apply_filters( “default_option_{$option}”, mixed $default_value, string $option, bool $passed_default )

Filters the default value for an option.

apply_filters( ‘pre_update_option’, mixed $value, string $option, mixed $old_value )

Filters an option before its value is (maybe) serialized and updated.

apply_filters( “pre_update_option_{$option}”, mixed $value, mixed $old_value, string $option )

Filters a specific option before its value is (maybe) serialized and updated.

do_action( ‘updated_option’, string $option, mixed $old_value, mixed $value )

Fires after the value of an option has been successfully updated.

do_action( ‘update_option’, string $option, mixed $old_value, mixed $value )

Fires immediately before an option value is updated.

do_action( “update_option_{$option}”, mixed $old_value, mixed $value, string $option )

Fires after the value of a specific option has been successfully updated.

Changelog

Version Description
6.7.0 The autoload values 'yes' and 'no' are deprecated.
4.2.0 The $autoload parameter was added.
1.0.0 Introduced.

User Contributed Notes

  1. Skip to note 14 content

    According to the WordPress Codex (and my experiences developing with WP) note an important subtlety in the return value here:
    “True if option value has changed, false if not or if update failed.

    It is also recommended on some forums to check for the existence of an option via code:

    if ( ! get_option('my_option') ) ...

    But I don’t find this works when the option exists and I have set my_option to bool FALSE!

    To handle all checking of existence of options, I exploit the update_option subtlety:

    if (FALSE === get_option('my_option') && FALSE === update_option('my_option',FALSE)) add_option('my_option',$default_value);

    The second check yields FALSE when setting the option with the value of FALSE produces no change…therefore if the value truly didn’t exist, it will be added with (in my case) the desired $default_value.

    I know this seems extreme, but to the best of my knowledge this is the only way I’ve been able to preserve bool FALSE on my plugin options, and to assert valid actions based on the actual presence of my custom options.

  2. Skip to note 15 content

    Since get_option in line 271 returns false if the option doesn’t yet exist, it is not possible to use update_option to create a new option with the boolean value false, because update_option would wrongly assume (line 307) that the option does exists but is unchanged. One workaround is to use as values integers 1 and 0 instead of booleans.

  3. Skip to note 16 content


    Anonymous User



    Update option only once on the first time installed
    The code below will let user change options even after new option set.

    function my_switch_theme() {
    	update_option( 'thumbnail_size_w', 320 );
    	update_option( 'thumbnail_size_h', 180 );
    }
    
    add_action('switch_theme', 'my_switch_theme');

    If we use after_setup_theme, it will block the options and prevent users change it.

  4. Skip to note 18 content

    update_option will return false if new value is same as old one.

    $opt_name  = ( ! empty($_POST['opt_name']  ) ) ? $_POST['opt_name']  : 'wpdocs';
    $opt_value = ( ! empty($_POST['opt_value'] ) ) ? $_POST['opt_value'] : ' ';
    		
    $existing_val = get_option( $opt_name );
    
    if ( false !== $existing_val ) {
    	// option exist
    	if ( $existing_val === $opt_value ) {
    		echo "new value is same as old.";
    	} else {
    		echo "new value is different.";
    		update_option( $opt_name, $opt_value );
    	}
    } else {
    	// option not exist
    	add_option( $opt_name, $opt_value );
    }

  5. Skip to note 20 content

    Example: Updating Custom Options
    You can also create your own custom options. This example updates the option 'my_custom_option' with the value 255:

    This will automatically add the option if it does not exist (and set the option’s value).

    If you don’t want your custom option to auto-load when WordPress starts up, use add_option(). This example updates the option if it already exists; if it does not exist it uses add_option() to set $autoload to 'no'.

  6. Skip to note 21 content

    Note
    Option values retrieved via WordPress functions are cached. If you modify an options outside of the Options API, then try to update a cached option, the update will fail and return false. Use the following method to clear the options cache before trying to get or update the options on the same request:

  7. Skip to note 23 content

    Update Option Stored in Multi-Dimensional Array

    update multi-dimensional array and retrieve the entire array.

    //store in one variable
    $multidimensional_options = array(
      'inner_array'=>array(
           'foo' => 'bar',
           'hello' => 'world',
       ),
    );
     
    //Update entire array
    update_option('my_multi_options', $multidimensional_options);
     
    //Get entire array
    $my_multi_options = get_option('my_multi_options');

  8. Skip to note 25 content

    Saving a boolean true will have the option value of (string) “1”.
    Saving a boolean false will have the option value of empty (string) “”;

    $value = true;
    update_option( 'some_option', $value );

    Getting a boolean value will return:
    a) the string “1” if the saved boolean was true
    b) the empty string “” if the saved boolean was false
    c) boolean false if the option doesn’t exist

    $get_value = get_option( 'some_option', true );

    To check if something was turned on, and it should be turned on by default (we don’t care if the option already exists):

    $check = ! empty( $get_value );

    To check if something was turned on, but only if the option exists:

    $check = ( '1' === $get_value );

  9. Skip to note 26 content

    As This function is designed to work with or without a logged-in user. Sometimes we have to check user capabilities.
    Let’s assume, our option should only be saved by admin user than code would be,

    global $current_user;
    
    $option_key   = 'option_key';
    $option_value = ( ! empty( $_POST['option_value_0'] ) && ! empty( $_POST['option_value_1'] ) ) ? array( $_POST['option_value_0'], $_POST['option_value_1'] ) : '';
    
    if ( current_user_can( 'manage_options' ) ) {
    	update_option( $option_key, $option_value );
    }

    Also, No need to serialize() the value, because function does itself.