函数文档

deactivate_plugins()

💡 云策文档标注

概述

deactivate_plugins() 函数用于停用单个或多个插件,支持静默模式以避免触发停用钩子,并可在多站点环境中控制停用范围。常用于插件依赖检查失败时自动停用自身。

关键要点

  • 参数 $plugins 接受字符串或数组,指定要停用的插件路径(基于 plugin_basename)。
  • 参数 $silent 默认为 false,设置为 true 可阻止调用 deactivate_plugin 和 deactivate_{$plugin} 等钩子。
  • 参数 $network_wide 用于多站点,控制停用范围:true 停用网络范围,false 仅当前站点,null 同时停用两者。
  • 函数内部处理 active_plugins 和 active_sitewide_plugins 选项的更新,并检查插件是否已激活。
  • 在恢复模式下,会从 wp_paused_plugins() 中移除相关扩展。

代码示例

// 示例:检查依赖并停用插件
add_action( 'admin_init', 'wpdocs_check_plugin_dependency' );
function wpdocs_check_plugin_dependency() {
  if ( ! is_plugin_active( 'wpdocs-some-other-plugin/plugin.php' ) && is_plugin_active( 'wpdocs-my-cool-plugin/plugin.php' ) ) {
    deactivate_plugins( 'wpdocs-my-cool-plugin/plugin.php' );
    wp_die( 'My Cool Plugin requires Some Other Plugin, and has therefore been deactivated!' );
  }
}

注意事项

  • 插件路径应使用 plugin_basename 格式,例如 my-plugin/my-plugin.php。
  • 静默停用(如插件升级时)不会触发相关动作钩子,需谨慎使用以避免副作用。
  • 在多站点环境中,需根据 $network_wide 参数正确处理网络和站点级别的停用逻辑。

📄 原文内容

Deactivates a single plugin or multiple plugins.

Description

The deactivation hook is disabled by the plugin upgrader by using the $silent parameter.

Parameters

$pluginsstring|string[]required
Single plugin or list of plugins to deactivate.
$silentbooloptional
Prevent calling deactivation hooks.

Default:false

$network_widebool|nulloptional
Whether to deactivate the plugin for all sites in the network.
A value of null will deactivate plugins for both the network and the current site. Multisite only.

Default:null

More Information

This function is often used by a plugin to deactivate itself if the plugin requires the presence of certain features that are missing in environment after an administrator has activated it. This is usually the last step in a dependency-checking function.

Source

function deactivate_plugins( $plugins, $silent = false, $network_wide = null ) {
	if ( is_multisite() ) {
		$network_current = get_site_option( 'active_sitewide_plugins', array() );
	}
	$current    = get_option( 'active_plugins', array() );
	$do_blog    = false;
	$do_network = false;

	foreach ( (array) $plugins as $plugin ) {
		$plugin = plugin_basename( trim( $plugin ) );
		if ( ! is_plugin_active( $plugin ) ) {
			continue;
		}

		$network_deactivating = ( false !== $network_wide ) && is_plugin_active_for_network( $plugin );

		if ( ! $silent ) {
			/**
			 * Fires before a plugin is deactivated.
			 *
			 * If a plugin is silently deactivated (such as during an update),
			 * this hook does not fire.
			 *
			 * @since 2.9.0
			 *
			 * @param string $plugin               Path to the plugin file relative to the plugins directory.
			 * @param bool   $network_deactivating Whether the plugin is deactivated for all sites in the network
			 *                                     or just the current site. Multisite only. Default false.
			 */
			do_action( 'deactivate_plugin', $plugin, $network_deactivating );
		}

		if ( false !== $network_wide ) {
			if ( is_plugin_active_for_network( $plugin ) ) {
				$do_network = true;
				unset( $network_current[ $plugin ] );
			} elseif ( $network_wide ) {
				continue;
			}
		}

		if ( true !== $network_wide ) {
			$key = array_search( $plugin, $current, true );
			if ( false !== $key ) {
				$do_blog = true;
				unset( $current[ $key ] );
			}
		}

		if ( $do_blog && wp_is_recovery_mode() ) {
			list( $extension ) = explode( '/', $plugin );
			wp_paused_plugins()->delete( $extension );
		}

		if ( ! $silent ) {
			/**
			 * Fires as a specific plugin is being deactivated.
			 *
			 * This hook is the "deactivation" hook used internally by register_deactivation_hook().
			 * The dynamic portion of the hook name, `$plugin`, refers to the plugin basename.
			 *
			 * If a plugin is silently deactivated (such as during an update), this hook does not fire.
			 *
			 * @since 2.0.0
			 *
			 * @param bool $network_deactivating Whether the plugin is deactivated for all sites in the network
			 *                                   or just the current site. Multisite only. Default false.
			 */
			do_action( "deactivate_{$plugin}", $network_deactivating );

			/**
			 * Fires after a plugin is deactivated.
			 *
			 * If a plugin is silently deactivated (such as during an update),
			 * this hook does not fire.
			 *
			 * @since 2.9.0
			 *
			 * @param string $plugin               Path to the plugin file relative to the plugins directory.
			 * @param bool   $network_deactivating Whether the plugin is deactivated for all sites in the network
			 *                                     or just the current site. Multisite only. Default false.
			 */
			do_action( 'deactivated_plugin', $plugin, $network_deactivating );
		}
	}

	if ( $do_blog ) {
		update_option( 'active_plugins', $current );
	}
	if ( $do_network ) {
		update_site_option( 'active_sitewide_plugins', $network_current );
	}
}

Hooks

do_action( ‘deactivated_plugin’, string $plugin, bool $network_deactivating )

Fires after a plugin is deactivated.

do_action( “deactivate_{$plugin}”, bool $network_deactivating )

Fires as a specific plugin is being deactivated.

Changelog

Version Description
2.5.0 Introduced.

User Contributed Notes

  1. Skip to note 4 content

    If you need to keep checking the dependency of another plugin, then you can hook the `admin_init` action to automatically deactivate the plugin should the other plugin be deactivated by administrator,

    add_action( 'admin_init', 'wpdocs_check_plugin_dependency' );
    function wpdocs_check_plugin_dependency() {
      // make sure to add your own plugin active check to stop looping over the wp_die call.
      if ( ! is_plugin_active( 'wpdocs-some-other-plugin/plugin.php' ) && is_plugin_active( 'wpdocs-my-cool-plugin/plugin.php' ) ) {
        deactivate_plugins( 'wpdocs-my-cool-plugin/plugin.php' );
            
        $button = '<a href="' . esc_attr( network_admin_url( 'plugins.php' ) . '" rel="nofollow ugc">Return to Plugins</a>';
        wp_die( '<strong>My Cool Plugin</strong> requires <strong>Some Other Plugin</strong>, and has therefore been deactivated!' . $button );
      }
    }

  2. Skip to note 5 content

    Example

    /**
     * Deactivate plugin example class.
     */
    class WPDocs_Deactivate_Plugin {
    
    	/**
    	 * Constructor.
    	 */
    	public function __construct() {
    		register_activation_hook( __FILE__, array( $this , 'activate' ) );
    	}
    
    	/**
    	 * Attempts to activate the plugin if at least PHP 5.4.
    	 */
    	public function activate() {
    		// Check PHP Version and deactivate & die if it doesn't meet minimum requirements.
    		if ( version_compare( PHP_VERSION, '5.4', '<=' ) ) {
    			deactivate_plugins( plugin_basename( __FILE__ ) );
    			wp_die( __( 'This plugin requires PHP Version 5.4 or greater.  Sorry about that.', 'textdomain' ) );
    		}
    		
    		// Do activate Stuff now.
    	}
    }
    new WPDocs_Deactivate_Plugin();

  3. Skip to note 6 content

    The “Plugin name” in the docs is referring to the plugin_basename, the relative path for your plugin itself. For example, if your plugin resides in wp-content/plugins/my-custom-plugin/my-custom-plugin.php, the plugin_basename you’d use for this function is my-custom-plugin/my-custom-plugin.php.