i am new to plugin development in wordpress and i have have this simple test plugin that i am working on. The problem i am having is that the uninstall.php file does not appear to get trigger and as such the database entried i wish to remove remain after the plugin in uninstalled from the WordPress admin.

Plugin code:

defined( 'ABSPATH' ) or die( 'Looks like you made a wrong turn there buddy' );

class TestPlugin

    function __construct() {
        add_action( 'init', array( $this, 'create_post_type' ) );

    function activate() {
        // generate a CPT in case 'init' fails
        // flush rewrite rules

    function deactivate() {
        // flush rewrite rules

    function uninstall() {
        // delete cpt
        // delete all the plugin data from the DB


    function create_post_type() {
        register_post_type( 'acme_product', array( 'public' => true, 'label' => 'Acme Product' ) );

if ( class_exists( 'TestPlugin' ) ) {
    $newTest = new TestPlugin();

// Activation
register_activation_hook( __FILE__, array( $newTest, 'activate' ) );

// Deactivation
register_activation_hook( __FILE__, array( $newTest, 'deactivate' ) );


 * Trigger this file on plugin uninstall
 * @package TestPlugin

if ( !defined( 'WP_UNINSTALL_PLUGIN' ) ) {

// Clear database stored data
//$acme_products = get_posts( array( 'post_type' => 'acme_product', 'numberposts' => -1 ) );
//foreach ( $acme_products as $acme_product) {
//    wp_delete_post( $acme_product->ID, true );

// Access the database via SQL
global $wpdb;
$wpdb->query( "DELETE FROM wp_posts WHERE post_type = 'acme_product'" );
$wpdb->query( "DELETE FROM wp_postmeta WHERE post_id NOT IN (SELECT id FROM wp_posts)" );
$wpdb->query( "DELETE FROM wp_term_relationships WHERE object_id NOT IN (SELECT id FROM wp_posts)" );


UPDATE: I have tested the SQL query just to make sure it worked in phpMyAdmin, and it works fine.

i.e "DELETE FROM wp_posts WHERE post_type = 'acme_product'"

  • 1
    Is the file name uninstall.php or Uninstall.php? Is it in the same subdirectory as the the main plugin file? – J.D. Nov 28 '17 at 13:42
  • file name is uninstall.php, all lowercase and is located in the same directory as the main plugin file. – Frederick M. Rogers Nov 28 '17 at 19:37
  • 1
    @J.D. Well it turns out you are the closest to a answer on this thread, in as much as yes i did spell it with a lowercase 'u' but i was missing an 'n'. Did not notice this until Drupalizeme asked me to navigate to the file in the browser. Though you should know :P – Frederick M. Rogers Dec 1 '17 at 19:50
  • :-D I think we've all probably spent hours debugging typoz... – J.D. Dec 1 '17 at 21:33

I don't see any issue with the uninstall besides the fact that echo a string(this interpreted us failed) and using hardcode prefix.

Below code have been tested locally with the latest version of WordPress.

// Access the database via SQL
global $wpdb;
$wpdb->query( "DELETE FROM {$wpdb->prefix}posts WHERE post_type = 'acme_product'" );
$wpdb->query( "DELETE FROM {$wpdb->prefix}postmeta WHERE post_id NOT IN (SELECT ID FROM {$wpdb->prefix}posts)" );
$wpdb->query( "DELETE FROM {$wpdb->prefix}term_relationships WHERE object_id NOT IN (SELECT ID FROM {$wpdb->prefix}posts)" );

  • Thanks, this makes sense. Made the changes to my queries but not the the database entry is not getting removed when plugin is deleted. – Frederick M. Rogers Nov 28 '17 at 19:35
  • Does the code run until the // Access the database via SQL global $wpdb; ? Can you disable all other plugins and try again? – Drupalizeme Nov 28 '17 at 19:42
  • Also, you are pressing the DELETE link correct? – Drupalizeme Nov 28 '17 at 19:50
  • i am using a clean wordpress install (on WAMP) with no other plugins installed. Not even Akizmet/Hello Dolly. And yes, i deactivate first then uninstall. I get the impression the file is not being called at all. That is why i added an echo to see if it would return som value. Is there a way to test if the uninstall.php file is being run? – Frederick M. Rogers Nov 28 '17 at 20:07
  • 1
    Remove this if ( !defined( 'WP_UNINSTALL_PLUGIN' ) ) { die; } Now can you navigate to the file and see if this is running? – Drupalizeme Nov 30 '17 at 7:35

Both of your hooks are register_activation_hook(). In order to hook into plugin's deactivation, you should use register_deactivation_hook() instead.

Also, this hook should not be confused with register_uninstall_hook(), which is best to be triggered after uninstalling a plugin.

You can read more about Activation/Deactivation hooks in the Plugin Handbook.

  • Can't believe i missed that, how ever the changing the hook to register_deactivation_hook() did not result in the database entry being removed on deletion of the project. I also tried @Drupalizeme suggestion and changed the prefixes to {$wpdb->prefix}. I an pretty sure there is a silly mistake somewhere. – Frederick M. Rogers Nov 28 '17 at 19:34

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.