A Bit Of History First:
On January 7th, 2008 I published an article that brought up a subject not many in the community at the time knew about. At the time, I had only used WordPress for a little over 7 months. I decided to venture into the database WordPress was installed in and discovered several discrepancies such as information from plugins I had recently deactivated and deleted from my installation were still inside the database. It turned out that some plugins were leaving their data, settings, or tables behind. This was a big deal at the time because it was occurring without users ever being aware of the problem. The post generated a great discussion on how this problem could be solved and I highlighted some of the best responses in a follow-up post.
At least some plugin authors were already ahead of the game by providing uninstallation features that would remove every trace of the plugin upon deactivation but that created yet another issue. We decided that there should be a clear distinction between deactivation and uninstallation. Deactivating would leave all settings and data in tact while uninstallation would remove everything. We as a community proposed the idea of an uninstall function being created to keep the separation between the two actions. I had also proposed that guidelines on the WordPress plugin repository be tightened up to the point where plugins were required to have an uninstall option but that idea was shot down because of the proposal of more restrictions. The following idea was first proposed by Alex:
The WP core should have an API hook for uninstalling a plugin. A plugin can register a certain function to this hook, if that function is called, the plugin will uninstall all its customizations. Then, if a plugin registered an uninstall function, add a link on the plugins page for the plugin to be uninstalled, e.g. right underneath “Deactive”. (Of course, uninstalling implies deactivitating.) Additionally, a plugin must have the ability to return if it was successful, and if it wasn’t, it must have a defined possibility to issue a message (e.g. steps to be performed manually).
Otto agreed with Alex.
Just like there are register_activation_hook and register_deactivation_hook functions, there needs to be a register_uninstall_hook function.
Having such a registered hook would allow the plugin page to create an uninstall link for that plugin. This link would only be available if the plugin was already inactive. This leads to a natural two step process: deactivate then remove. We don’t want an implied deactivation, since this forces plugin authors to consider two different approaches to deactivation and uninstallation. Keep it simple.
The uninstall button will call the uninstall hook for the plugin, which would take appropriate action to remove its options and tables and such.
Seems like the best solution and keeps the interface clean and easy.
That discussion took place at the beginning of 2008. At the end of 2008, WordPress 2.7 “Coltrane” was released to the world. The two biggest changes in WordPress 2.7 was the user interface redesign and the addition of auto-upgrades. But there was one more important addition in 2.7 that didn’t garner very much attention, register uninstall hook. This hook as well as uninstall.php allowed the deactivation and uninstallation of plugins to be separate processes.
Despite the presence of the uninstall hook, the emphasis is put on using the uninstall.php method. Not knowing why, I reached out to a guy that has over 50 plugins tied to his name, Scott Reilly. The following is our conversation which provides a clearer understanding of why one method is better than the other.
Jeff – Can you please explain why the uninstall.php method is the preferred method of uninstalling a plugin and its data versus using the uninstall hook?
Scott – It prevents the main plugin file from being run during uninstall, which can be problematic if the plugin runs code in the global space. It’s also better in that the uninstall code is centralized.
Jeff – Ok. Uninstall.php contains the uninstallation process while the hook can cause trouble. So as a plugin author, I would have control over and know exactly what is going to happen when using uninstall.php but if I were to rely on the hook, I wouldn’t exactly know what will happen, until the process occurs? Is my thinking correct?
Scott – Yes. If uninstall.php is present, that will be run when the plugin is uninstalled. If not present, then the main plugin file is run to check for the hook usage. depending on how the plugin is coded, it can cause problems if code is run in the global space (i.e. evaluated when the file is executed rather than properly wrapped into functions/classes that are called as needed). If you know what you’re doing, the hook can be used without ill effect. It’s safer to use uninstall.php, and a simpler recommendation to give most people.
Plugin authors will need to first verify that register_uninstall_hook function exists because it didn’t prior to WordPress 2.7. Next, you’ll call your custom uninstall function to properly uninstall your plugin options. If you add uninstall functionality to your plugin, please add a warning of some type so that users will know that all data will be lost once the uninstallation process finishes.
Still A Problem:
While cleaning up my database trying to figure out my performance problems, I noticed that there were a few tables created by plugins I had deleted a few years ago. Some of the tables contained a number of entries while others were just empty, but their unneeded presence annoyed me. This tells me that five years after the necessary functions were added to WordPress to uninstall plugins, plugin authors are still not utilizing them.
This is my polite as can be request for authors of plugins that create, add or manipulate the database in any way to give end users the opportunity to restore their WordPress installation back to the way it was before they installed your plugin. To this day, users don’t have any idea about what is really going on in their database without actually going inside via phpMyAdmin which is always risky. I place this responsibility solely on the backs of plugin authors.
Jacob Santos published a detailed post explaining the different plugin uninstallation methods.
WordPress Hackers discussion in 2010 that discussed both options for uninstalling plugins. Be warned though, not every post maybe relevant to the original topic.
Last but not least, check out the WPDB SpringClean plugin. This plugin will identify unoptimized tables and will allow you to optimize them by deleting the allocated unused space within a particular table. The plugin also optionally allows you to specify search criteria such as the minimum amount of overhead per table and minimum unused space for a table. (Anytime you perform work that involves the database, you should ALWAYS back up before moving forward.) Hat tip to Brad Williams.