Master WordPress Plugin Lifecycle management. Learn to handle version-specific database migrations and implement professional, non-destructive uninstall routines.
Previously in this course, we covered Versioning and Release Management: Professional WordPress Plugin Standards. While versioning handles the "what" and "when" of your updates, this lesson focuses on the "how"—specifically, managing the state of your plugin’s data as it evolves over time.
Professional plugin engineering requires more than just adding features; it demands a defensive approach to how your code interacts with the WordPress database during installation, updates, and removal.
A robust plugin lifecycle is governed by three primary events: activation, updates, and uninstallation. In a production-grade plugin, these should never be handled by scattered logic in your main plugin file. Instead, we treat the lifecycle as a series of state transitions.
As discussed in Integration Testing for WordPress: Database and API Workflows, database changes are the most common source of production outages. You should never rely on simple dbDelta calls without tracking the current version of your schema.
We implement a MigrationManager that checks the version stored in wp_options against the current plugin version constant.
PHPnamespace MyPlugin\Lifecycle; class MigrationManager { public function maybe_migrate() { $installed_version = get_option('my_plugin_version', '0.0.0'); $current_version = MY_PLUGIN_VERSION; if (version_compare($installed_version, $current_version, '<')) { $this->run_migrations($installed_version, $current_version); update_option('my_plugin_version', $current_version); } } private function run_migrations($from, $to) { #6A9955">// Logic to execute specific SQL files based on version gaps if (version_compare($from, '1.1.0', '<')) { $this->migrate_to_1_1_0(); } } }
The uninstall.php file is a special file that WordPress executes only when a user deletes a plugin from the admin dashboard. Note that this file runs in a separate process, meaning it does not have access to your defined classes or constants.
Crucial: Always check defined('WP_UNINSTALL_PLUGIN') to prevent direct access to the file.
PHP#6A9955">// uninstall.php if (!defined('WP_UNINSTALL_PLUGIN')) { exit; } global $wpdb; #6A9955">// Only delete data if the user hasn't opted to "Keep Data" $keep_data = get_option('my_plugin_keep_data_on_uninstall', false); if (!$keep_data) { $wpdb->query("DROP TABLE IF EXISTS {$wpdb->prefix}my_plugin_data"); delete_option('my_plugin_settings'); }
Your task is to integrate a migration check into the plugin's boot process.
LifecycleServiceProvider that hooks into admin_init.MY_PLUGIN_VERSION constant.my_plugin_version option.$wpdb->prepare as defined in Preventing SQL Injection in WordPress: A Deep Dive into $wpdb.uninstall.php: As noted, uninstall.php is isolated. Keep your logic procedural here. If you need to share logic, use a separate file that you require carefully, ensuring no dependencies on the main plugin bootstrapper.is_network_admin() checks if you are modifying global tables.Proper lifecycle management ensures your plugin is a "good citizen" in the WordPress ecosystem. By versioning your database schema, using uninstall.php defensively, and providing users control over their data, you build trust and maintain stability. Always treat your database as the long-lived component of your software that must survive even when the plugin code itself is removed.
Up next: Performance Monitoring — adding instrumentation to track query times and system health.
Master Gutenberg dynamic block rendering in PHP. Learn to implement render_callback, optimize server-side performance, and cache output for high-traffic sites.
Read moreMaster the architecture of Multisite-ready WordPress plugins. Learn to implement site-specific data isolation and network-wide management for scalable plugins.
Plugin Lifecycle Management
Custom Hooks for React