函数文档

wp_set_option_autoload_values()

💡 云策文档标注

概述

wp_set_option_autoload_values() 函数用于批量设置数据库中多个选项的 autoload 值,以优化性能,避免因过多选项自动加载导致的问题。它常用于插件激活或停用钩子中,调整相关选项的 autoload 状态。

关键要点

  • 函数接受一个关联数组参数 $options,键为选项名,值为 autoload 值(布尔类型,向后兼容 'yes'/'no',但已弃用)。
  • 返回一个关联数组,键为提供的选项名,值为布尔值,表示是否成功更新 autoload 值。
  • 内部通过 wpdb 执行 SQL 查询,最多运行两次 UPDATE 操作,并自动处理缓存更新(如 wp_cache_delete_multiple 和 wp_cache_set)。
  • 函数会调用 wp_protect_special_option() 确保只处理有效选项,并支持 'on'/'off' 和 'yes'/'no' 值以保持向后兼容。

代码示例

// 示例:设置多个选项的 autoload 值
$options = array(
    'my_plugin_option1' => true,
    'my_plugin_option2' => false,
);
$results = wp_set_option_autoload_values($options);
// $results 将包含更新状态,例如 array('my_plugin_option1' => true, 'my_plugin_option2' => true)

注意事项

  • autoload 值应使用布尔类型(true/false),避免使用已弃用的 'yes'/'no' 字符串。
  • 选项名不应进行 SQL 转义,函数内部会处理安全性。
  • 更新 autoload 值不会改变选项的实际值,仅影响其是否在 WordPress 启动时自动加载。

📄 原文内容

Sets the autoload values for multiple options in the database.

Description

Autoloading too many options can lead to performance problems, especially if the options are not frequently used.
This function allows modifying the autoload value for multiple options without changing the actual option value.
This is for example recommended for plugin activation and deactivation hooks, to ensure any options exclusively used by the plugin which are generally autoloaded can be set to not autoload when the plugin is inactive.

Parameters

$optionsarrayrequired
Associative array of option names and their autoload values to set. The option names are expected to not be SQL-escaped. The autoload values should be boolean values. For backward compatibility 'yes' and 'no' are also accepted, though using these values is deprecated.

Return

array Associative array of all provided $options as keys and boolean values for whether their autoload value was updated.

Source

function wp_set_option_autoload_values( array $options ) {
	global $wpdb;

	if ( ! $options ) {
		return array();
	}

	$grouped_options = array(
		'on'  => array(),
		'off' => array(),
	);
	$results         = array();
	foreach ( $options as $option => $autoload ) {
		wp_protect_special_option( $option ); // Ensure only valid options can be passed.

		/*
		 * Sanitize autoload value and categorize accordingly.
		 * The values 'yes', 'no', 'on', and 'off' are supported for backward compatibility.
		 */
		if ( 'off' === $autoload || 'no' === $autoload || false === $autoload ) {
			$grouped_options['off'][] = $option;
		} else {
			$grouped_options['on'][] = $option;
		}
		$results[ $option ] = false; // Initialize result value.
	}

	$where      = array();
	$where_args = array();
	foreach ( $grouped_options as $autoload => $options ) {
		if ( ! $options ) {
			continue;
		}
		$placeholders = implode( ',', array_fill( 0, count( $options ), '%s' ) );
		$where[]      = "autoload != '%s' AND option_name IN ($placeholders)";
		$where_args[] = $autoload;
		foreach ( $options as $option ) {
			$where_args[] = $option;
		}
	}
	$where = 'WHERE ' . implode( ' OR ', $where );

	/*
	 * Determine the relevant options that do not already use the given autoload value.
	 * If no options are returned, no need to update.
	 */
	// phpcs:ignore WordPress.DB.PreparedSQL.InterpolatedNotPrepared,WordPress.DB.PreparedSQLPlaceholders.UnfinishedPrepare
	$options_to_update = $wpdb->get_col( $wpdb->prepare( "SELECT option_name FROM $wpdb->options $where", $where_args ) );
	if ( ! $options_to_update ) {
		return $results;
	}

	// Run UPDATE queries as needed (maximum 2) to update the relevant options' autoload values to 'yes' or 'no'.
	foreach ( $grouped_options as $autoload => $options ) {
		if ( ! $options ) {
			continue;
		}
		$options                      = array_intersect( $options, $options_to_update );
		$grouped_options[ $autoload ] = $options;
		if ( ! $grouped_options[ $autoload ] ) {
			continue;
		}

		// Run query to update autoload value for all the options where it is needed.
		$success = $wpdb->query(
			$wpdb->prepare(
				"UPDATE $wpdb->options SET autoload = %s WHERE option_name IN (" . implode( ',', array_fill( 0, count( $grouped_options[ $autoload ] ), '%s' ) ) . ')',
				array_merge(
					array( $autoload ),
					$grouped_options[ $autoload ]
				)
			)
		);
		if ( ! $success ) {
			// Set option list to an empty array to indicate no options were updated.
			$grouped_options[ $autoload ] = array();
			continue;
		}

		// Assume that on success all options were updated, which should be the case given only new values are sent.
		foreach ( $grouped_options[ $autoload ] as $option ) {
			$results[ $option ] = true;
		}
	}

	/*
	 * If any options were changed to 'on', delete their individual caches, and delete 'alloptions' cache so that it
	 * is refreshed as needed.
	 * If no options were changed to 'on' but any options were changed to 'no', delete them from the 'alloptions'
	 * cache. This is not necessary when options were changed to 'on', since in that situation the entire cache is
	 * deleted anyway.
	 */
	if ( $grouped_options['on'] ) {
		wp_cache_delete_multiple( $grouped_options['on'], 'options' );
		wp_cache_delete( 'alloptions', 'options' );
	} elseif ( $grouped_options['off'] ) {
		$alloptions = wp_load_alloptions( true );

		foreach ( $grouped_options['off'] as $option ) {
			if ( isset( $alloptions[ $option ] ) ) {
				unset( $alloptions[ $option ] );
			}
		}

		wp_cache_set( 'alloptions', $alloptions, 'options' );
	}

	return $results;
}

Changelog

Version Description
6.7.0 The autoload values 'yes' and 'no' are deprecated.
6.4.0 Introduced.