* Retrieves an option value based on an option name.
* If the option does not exist or does not have a value, then the return value
* will be false. This is useful to check whether you need to install an option
* and is commonly used during installation of plugin options and to test
* whether upgrading is required.
* If the option was serialized then it will be unserialized when it is returned.
* Any scalar values will be returned as strings. You may coerce the return type of
* a given option by registering an {@see 'option_$option'} filter callback.
* @global wpdb $wpdb WordPress database abstraction object.
* @param string $option Name of the option to retrieve. Expected to not be SQL-escaped.
* @param mixed $default Optional. Default value to return if the option does not exist.
* @return mixed Value set for the option. A value of any type may be returned, including
* array, boolean, float, integer, null, object, and string.
function get_option( $option, $default = false ) {
$option = trim( $option );
if ( empty( $option ) ) {
* 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 ( ! wp_installing() && isset( $deprecated_keys[ $option ] ) ) {
/* translators: 1: Deprecated option key, 2: New option key. */
__( 'The "%1$s" option key has been renamed to "%2$s".' ),
$deprecated_keys[ $option ]
return get_option( $deprecated_keys[ $option ], $default );
* Filters the value of an existing option before it is retrieved.
* The dynamic portion of the hook name, `$option`, refers to the option name.
* Returning a truthy value from the filter will effectively short-circuit retrieval
* and return the passed value instead.
* @since 4.4.0 The `$option` parameter was added.
* @since 4.9.0 The `$default` parameter was added.
* @param mixed $pre_option The value to return instead of the option value. This differs
* from `$default`, which is used as the fallback value in the event
* the option doesn't exist elsewhere in get_option().
* Default false (to skip past the short-circuit).
* @param string $option Option name.
* @param mixed $default The fallback value to return if the option does not exist.
$pre = apply_filters( "pre_option_{$option}", false, $option, $default );
if ( defined( 'WP_SETUP_CONFIG' ) ) {
// Distinguish between `false` as a default, and not passing one.
$passed_default = func_num_args() > 1;
if ( ! wp_installing() ) {
// Prevent non-existent options from triggering multiple queries.
$notoptions = wp_cache_get( 'notoptions', 'options' );
if ( isset( $notoptions[ $option ] ) ) {
* Filters the default value for an option.
* The dynamic portion of the hook name, `$option`, refers to the option name.
* @since 4.4.0 The `$option` parameter was added.
* @since 4.7.0 The `$passed_default` parameter was added to distinguish between a `false` value and the default parameter value.
* @param mixed $default The default value to return if the option does not exist
* @param string $option Option name.
* @param bool $passed_default Was `get_option()` passed a default value?
return apply_filters( "default_option_{$option}", $default, $option, $passed_default );
$alloptions = wp_load_alloptions();
if ( isset( $alloptions[ $option ] ) ) {
$value = $alloptions[ $option ];
$value = wp_cache_get( $option, 'options' );
if ( false === $value ) {
$row = $wpdb->get_row( $wpdb->prepare( "SELECT option_value FROM $wpdb->options WHERE option_name = %s LIMIT 1", $option ) );
// Has to be get_row() instead of get_var() because of funkiness with 0, false, null values.
if ( is_object( $row ) ) {
$value = $row->option_value;
wp_cache_add( $option, $value, 'options' );
} else { // Option does not exist, so we must cache its non-existence.
if ( ! is_array( $notoptions ) ) {
$notoptions[ $option ] = true;
wp_cache_set( 'notoptions', $notoptions, 'options' );
/** This filter is documented in wp-includes/option.php */
return apply_filters( "default_option_{$option}", $default, $option, $passed_default );
$suppress = $wpdb->suppress_errors();
$row = $wpdb->get_row( $wpdb->prepare( "SELECT option_value FROM $wpdb->options WHERE option_name = %s LIMIT 1", $option ) );
$wpdb->suppress_errors( $suppress );
if ( is_object( $row ) ) {
$value = $row->option_value;
/** This filter is documented in wp-includes/option.php */
return apply_filters( "default_option_{$option}", $default, $option, $passed_default );
// If home is not set, use siteurl.
if ( 'home' === $option && '' === $value ) {
return get_option( 'siteurl' );
if ( in_array( $option, array( 'siteurl', 'home', 'category_base', 'tag_base' ), true ) ) {
$value = untrailingslashit( $value );
* Filters the value of an existing option.
* The dynamic portion of the hook name, `$option`, refers to the option name.
* @since 1.5.0 As 'option_' . $setting
* @since 4.4.0 The `$option` parameter was added.
* @param mixed $value Value of the option. If stored serialized, it will be
* unserialized prior to being returned.
* @param string $option Option name.
return apply_filters( "option_{$option}", maybe_unserialize( $value ), $option );
* Protects WordPress special option from being modified.
* Will die if $option is in protected list. Protected options are 'alloptions'
* and 'notoptions' options.
* @param string $option Option name.
function wp_protect_special_option( $option ) {
if ( 'alloptions' === $option || 'notoptions' === $option ) {
/* translators: %s: Option name. */
__( '%s is a protected WP option and may not be modified' ),
* Prints option value after sanitizing for forms.
* @param string $option Option name.
function form_option( $option ) {
echo esc_attr( get_option( $option ) );
* Loads and caches all autoloaded options, if available or all options.
* @since 5.3.1 The `$force_cache` parameter was added.
* @global wpdb $wpdb WordPress database abstraction object.
* @param bool $force_cache Optional. Whether to force an update of the local cache
* from the persistent cache. Default false.
* @return array List of all options.
function wp_load_alloptions( $force_cache = false ) {
if ( ! wp_installing() || ! is_multisite() ) {
$alloptions = wp_cache_get( 'alloptions', 'options', $force_cache );
$suppress = $wpdb->suppress_errors();
$alloptions_db = $wpdb->get_results( "SELECT option_name, option_value FROM $wpdb->options WHERE autoload = 'yes'" );
if ( ! $alloptions_db ) {
$alloptions_db = $wpdb->get_results( "SELECT option_name, option_value FROM $wpdb->options" );
$wpdb->suppress_errors( $suppress );
foreach ( (array) $alloptions_db as $o ) {
$alloptions[ $o->option_name ] = $o->option_value;
if ( ! wp_installing() || ! is_multisite() ) {
* Filters all options before caching them.
* @param array $alloptions Array with all options.
$alloptions = apply_filters( 'pre_cache_alloptions', $alloptions );
wp_cache_add( 'alloptions', $alloptions, 'options' );
* Filters all options after retrieving them.
* @param array $alloptions Array with all options.
return apply_filters( 'alloptions', $alloptions );
* Loads and caches certain often requested site options if is_multisite() and a persistent cache is not being used.
* @global wpdb $wpdb WordPress database abstraction object.
* @param int $network_id Optional site ID for which to query the options. Defaults to the current site.
function wp_load_core_site_options( $network_id = null ) {
if ( ! is_multisite() || wp_using_ext_object_cache() || wp_installing() ) {
if ( empty( $network_id ) ) {
$network_id = get_current_network_id();
$core_options = array( 'site_name', 'siteurl', 'active_sitewide_plugins', '_site_transient_timeout_theme_roots', '_site_transient_theme_roots', 'site_admins', 'can_compress_scripts', 'global_terms_enabled', 'ms_files_rewriting' );
$core_options_in = "'" . implode( "', '", $core_options ) . "'";
$options = $wpdb->get_results( $wpdb->prepare( "SELECT meta_key, meta_value FROM $wpdb->sitemeta WHERE meta_key IN ($core_options_in) AND site_id = %d", $network_id ) );
foreach ( $options as $option ) {
$key = $option->meta_key;
$cache_key = "{$network_id}:$key";
$option->meta_value = maybe_unserialize( $option->meta_value );
wp_cache_set( $cache_key, $option->meta_value, 'site-options' );
* Updates the value of an option that was already added.
* 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.
* @since 4.2.0 The `$autoload` parameter was added.
* @global wpdb $wpdb WordPress database abstraction object.
* @param string $option Name of the option to update. Expected to not be SQL-escaped.
* @param mixed $value Option value. Must be serializable if non-scalar. Expected to not be SQL-escaped.
* @param string|bool $autoload Optional. Whether to load the option when WordPress starts up. For existing options,
* `$autoload` can only be updated using `update_option()` if `$value` is also changed.
* Accepts 'yes'|true to enable or 'no'|false to disable. For non-existent options,
* the default value is 'yes'. Default null.
* @return bool True if the value was updated, false otherwise.
function update_option( $option, $value, $autoload = null ) {
$option = trim( $option );
if ( empty( $option ) ) {
* 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 ( ! wp_installing() && isset( $deprecated_keys[ $option ] ) ) {
/* translators: 1: Deprecated option key, 2: New option key. */
__( 'The "%1$s" option key has been renamed to "%2$s".' ),
$deprecated_keys[ $option ]
return update_option( $deprecated_keys[ $option ], $value, $autoload );
wp_protect_special_option( $option );
if ( is_object( $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 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.
* @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 ) ) {
/** This filter is documented in wp-includes/option.php */
if ( apply_filters( "default_option_{$option}", false, $option, false ) === $old_value ) {
// Default setting for new options is 'yes'.
if ( null === $autoload ) {
return add_option( $option, $value, '', $autoload );
$serialized_value = maybe_serialize( $value );
* Fires immediately before an option value is updated.
* @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 );
'option_value' => $serialized_value,
if ( null !== $autoload ) {
$update_args['autoload'] = ( 'no' === $autoload || false === $autoload ) ? 'no' : 'yes';
$result = $wpdb->update( $wpdb->options, $update_args, array( 'option_name' => $option ) );
$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() ) {
$alloptions = wp_load_alloptions( true );
if ( isset( $alloptions[ $option ] ) ) {
$alloptions[ $option ] = $serialized_value;
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 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.
* @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 );
* 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.
* You can create options without values and then update the values later.
* Existing options will not be updated and checks are performed to ensure that you
* aren't adding a protected WordPress option. Care should be taken to not name