register_deactivation_hook( string $file, callable $callback )

Sets the deactivation hook for a plugin.

Description

When a plugin is deactivated, the action ‘deactivate_PLUGINNAME’ hook is called. In the name of this hook, PLUGINNAME is replaced with the name of the plugin, including the optional subdirectory. For example, when the plugin is located in wp-content/plugins/sampleplugin/sample.php, then the name of this hook will become ‘deactivate_sampleplugin/sample.php’.

When the plugin consists of only one file and is (as by default) located at wp-content/plugins/sample.php the name of this hook will be ‘deactivate_sample.php’.

Parameters

$filestringrequired
The filename of the plugin including the path.
$callbackcallablerequired
The function hooked to the 'deactivate_PLUGIN' action.

Source

function register_deactivation_hook( $file, $callback ) {
	$file = plugin_basename( $file );
	add_action( 'deactivate_' . $file, $callback );
}

Changelog

VersionDescription
2.0.0Introduced.

User Contributed Notes

  1. Skip to note 4 content

    Examples
    If you have a function called myplugin_deactivate() in the main plugin file at either

    wp-content/plugins/myplugin.php or
    wp-content/plugins/myplugin/myplugin.php
    use this code:

    register_deactivation_hook( __FILE__, 'myplugin_deactivate' );

    This will call the myplugin_deactivate() function on deactivation of the plugin.

  2. Skip to note 5 content

    If you are using a namespace in the main plugin file
    namespace MYNAMESAPCE;

    you will need to use the __NAMESPACE__ keyword in your code for register_deactivation_hook.
    register_deactivation_hook( __FILE__ , __NAMESPACE__ . '\deactivate_plugin' );

    Otherwise, the code will be unable to find the function deactivate_plugin() and will produce a warning:
    PHP Warning: call_user_func_array() expects parameter 1 to be a valid callback, function ‘deactivate_plugin’ not found.

  3. Skip to note 6 content

    It is important to note that despite deactivation and uninstall hooks being available since WP 2.0 and 2.7 respectively, there are still a lot of plugins around that do not properly clean up after themselves, cluttering the database with useless data.

    A useful difference between register_deactivation_hook and both register_uninstall_hook and uninstall.php is that our deactivation hook callback is run when the plugin is still active. This means this is the last opportunity to run code that is integrally part of the plugin, without having to purposely load specific parts of the plugin or write very large uninstall routines.

    So preparing a plugin for a clean uninstall, you might need both these tools: (1) the deactivation action for complicated plugin-specific tasks that need plugin internals, for example removing metadata or transients named variably on user settings and (2) the uninstall action (or better: uninstall.php) to run broader / less complicated tasks like removing a known list of options with delete_option(), removing plugin specific database tables or (cache) files.

    An example code of an deactivation callback using a plugin internal method, prepared for both regular and network deactivation:

    register_deactivation_hook( __FILE__, array( 'MyPlugin', 'deactivate' ) );
    
    class MyPlugin {
    
    	// ...
    
    	/**
    	 * Clear plugin data that might be hard to find without the plugin being active.
    	 *
    	 * @since x.x
    	 */
    	public static function cleanup() {
    		// ...
    	}
    
    	/**
    	 * Plugin deactivation.
    	 *
    	 * @since x.x
    	 *
    	 * @param bool $network_deactivating Whether the plugin is network deactivated or not.
    	 */
    	public static function deactivate( $network_deactivating = false ) {
    		if ( $network_deactivating && ! wp_is_large_network() ) {
    			$_ids = get_sites(
    				array(
    					'fields' => 'ids',
    					'number' => -1,
    				)
    			);
    
    			foreach ( $_ids as $_id ) {
    				switch_to_blog( $_id );
    
    				self::cleanup();
    
    				restore_current_blog();
    			}
    		} else {
    			self::cleanup();
    		}
    	}
    }

    Note: one specific problem occurs when your plugin has custom rewrite rules and you need to do revert those on deactivation. A simple flush_rewrite_rules() will not work here, due exactly to the fact that the plugin is still active. You’ll need to take care to undo all plugin rewrite rules added with add_rewrite_rule() before flushing but sadly, a simple function like remove_rewrite_rule() does not exist (yet?)…

You must log in before being able to contribute a note or feedback.