Plugin Developers – Use Uninstall.php Please

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.

The Implementation:

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.

Further Reading:

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.

8 Comments


  1. Hi Jeff,

    Great post! I’ve only been using WordPress for a year now and just started developing plugins. I often find orphaned tables and directories and wonder why some plugin developers focus primarily on the set-up and not enough on the tear-down.

    When I started working on my current plugin, I determined that it needed a database table. So the first thing I did was make sure the table was created properly on activation, and dropped properly on uninstall, but I only knew about the uninstall hook. I like the thought of keeping the Uninstall code in a separate file, it feels clean. So I’m going to adopt that practice and refactor my current plugin right away!

    Thank you for sharing!

    Report


  2. I agree that in most situations that the core WordPress uninstall.php functionality should be used for uninstall situations involving plugins.

    However, with Gravity Forms we have our own uninstall process and implementation. Because of the fact our product is commonly used for information that is considered critical and vital to a business, the accidental deletion of it is something you want to avoid.

    To put it bluntly, some users are dumb. They may not realize “Uninstall” means they would lose ALL of their data. They may use it when they are simply playing around with their site and removing and adding a different version of the plugin, etc. not realizing the implications. They may not realizing that by “deleting” a plugin it’s going to delete ALL of the data and tables that may be associated with that plugin.

    For instance it’s common for us to deactivate and delete versions of GF and Add-Ons on our own test machines via the plugin manager and then upload and install different versions. That doesn’t mean we want to lose all our data. So we certainly don’t want that to occur when we delete the plugin in the plugin manager.

    This is why we chose to implement our own version of a full uninstall within the Gravity Forms Settings area that makes it very clear to the end users that it will delete ALL data and remove ALL database tables.

    So one size definitely doesn’t fit all. But our plugin is atypical. For a lot of plugins the core uninstall.php functionality should be utilized. But that doesn’t mean it should be used by all plugins.

    Report


  3. @Carl Hancock – Well you’ve proven to me once again that there usually is no one size fits all. The scenario and situation you provided certainly makes sense for GravityForms. I certainly wouldn’t want to accidentally delete everything after removing GravityForms which is why I think it’s good that you’ve turned it into it’s own unique separate process with a big warning. But, I think GForms is an edge case scenario along with perhaps a few other plugins but I bet the majority of plugins would be just fine with the Uninstall.php method.

    At any rate, I’m glad you wrote your comment to give other plugin developers a different perspective on when it might not be best to go with either the hook or uninstall.php. The one thing I’d hate to see are general typical plugins all coming up with their own uninstall methods.

    Report


  4. @Jeffro – I’ve made sure I include uninstall.php in all my plugins that deletes the data. But, I clearly understand Carl’s point above.

    I think a good thing would be that when a person is deleting the plugin via the Plugin Installer, WordPress warns the users that he might lose all data added by the plugin.

    Report


  5. @Ajay – Yes, which is why I added 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. to the post but I think I’ll need to bold the entire statement so people see it.

    Report


  6. @Jeffro – Actually, I meant WordPress needs to add this just before the user hits the delete button.

    Agreed it’s definitely a good idea to throw it somewhere in the plugin

    Report


  7. That’s why I’d like to use SQLite to store the options for my plugins. Although I’m just beginning to learn the WordPress plugin development, I think that WordPress relied too much on MySQL database.

    Report


Comments are closed.