Skip to main content
WP HealthKit

WordPress Plugin PHP Deprecation: A Full Migration Guide

June 27, 202618 min readQualityBy Jamie

Every WordPress plugin eventually encounters deprecated PHP functions. The code that worked perfectly in PHP 5.6 has become a legacy burden in PHP 8.x. Yet many plugin developers ignore these warnings until users complain about broken functionality or hosting providers force upgrades.

WordPress plugin PHP deprecated functions migration isn't glamorous work—it won't add features or attract users. But it's critical maintenance that prevents future crashes, improves performance, and keeps your codebase compatible with modern hosting environments.

This guide covers identifying deprecated functions, understanding WordPress-specific deprecations, planning migration strategies, and testing after changes. WP HealthKit can scan your plugin to detect deprecated functions and compatibility issues, providing a roadmap for modernization.

Table of Contents

  1. Understanding PHP Deprecations
  2. Identifying Deprecated Functions in Your Plugin
  3. WordPress-Specific Function Deprecations
  4. Planning Your Migration Strategy
  5. Common PHP Deprecations and Solutions
  6. Automated Detection Tools
  7. Testing After Migration
  8. Frequently Asked Questions

Understanding PHP Deprecations

When PHP developers deprecate a function, they're saying: "This function still works, but we're warning that it will be removed in a future version. Plan to stop using it."

There are three levels of PHP function lifecycle:

Active: Function works, no warnings. Code using it runs normally.

Deprecated: Function works but generates deprecation warnings when used. PHP continues to execute the code, but the function will be removed in a future version. Users may see warnings in debug logs.

Removed: Function no longer exists. Code using it causes a fatal error and the site crashes.

WordPress plugin PHP deprecation follows a similar pattern, but WordPress-specific deprecations often have longer timelines. WordPress 5.x marked functions as deprecated that won't be removed until WordPress 7.x or later.

Here's the progression:

// PHP 5.6: Function works, no warnings
function old_function() {
    // Code works normally
}

// PHP 7.0: Function deprecated (E_DEPRECATED)
function old_function() {
    // Still works but triggers a deprecation notice
    trigger_error('Use new_function() instead', E_DEPRECATED);
    // Code executes anyway
}

// PHP 8.0+: Function removed (fatal error)
// Calling old_function() causes:
// Fatal error: Call to undefined function old_function()

Why deprecations matter:

  1. Hosting environments change: Most hosts have upgraded to PHP 8.0+
  2. Security: Old functions sometimes have security issues that won't be fixed
  3. Performance: Newer functions are often optimized
  4. Compatibility: Plugins using old functions can't be used with newer PHP versions
  5. Technical debt: Putting off migration makes future upgrades more expensive

The progression from deprecated to removed happens over years, giving you time to migrate. But if you ignore deprecation warnings long enough, you'll eventually have a crisis. A user upgrades to PHP 8.2, their hosting provider forces the upgrade, or they switch hosts and the new host runs PHP 8.1. Suddenly your plugin breaks catastrophically. Your plugin stops working entirely—not just with reduced functionality, but completely broken. Users complain. Your plugin rating drops. You scramble to fix it.

Identifying Deprecated Functions in Your Plugin

The first step is discovering what deprecated functions you're using. There are several approaches. You can't fix what you don't know about. Many plugins have deprecated code that the developers never discovered because they didn't have the right tools or didn't test against newer PHP versions. Some developers intentionally ignore deprecation warnings, assuming the function will work "forever." Others simply never test their code against development PHP versions where deprecation warnings are visible.

The key is choosing detection methods that work for your development process. If you're running tests in CI/CD, static analysis tools like PHPStan catch deprecations automatically. If you have a staging environment running PHP 8.x with debug logging enabled, runtime warnings appear in logs. Some approaches are proactive (finding deprecations before users encounter them), others are reactive (learning about them when errors appear in production).

PHP error logs approach:

Enable error reporting in your development environment:

// wp-config.php
define('WP_DEBUG', true);
define('WP_DEBUG_LOG', true);
define('WP_DEBUG_DISPLAY', false);

// This creates /wp-content/debug.log
// Deprecated functions will be logged as warnings

Then run your plugin's features and check the debug log:

[18-Mar-2026 10:15:23 UTC] PHP Deprecated:  Array access on objects is deprecated in /wp-content/plugins/my-plugin/includes/processor.php on line 234
[18-Mar-2026 10:15:45 UTC] PHP Deprecated:  Implicitly marking parameter $foo as nullable is deprecated, the explicit nullable type must be used instead in /wp-content/plugins/my-plugin/src/class-handler.php on line 145

PHPStan static analysis:

PHPStan can detect deprecated function usage without running the code:

# Install PHPStan with WordPress rules
composer require --dev phpstan/phpstan phpstan/extension-installer szepeviktor/phpstan-wordpress

# Create phpstan.neon configuration
mkdir phpstan-configs
cat > phpstan.neon << 'EOF'
includes:
    - extension.neon

parameters:
    level: 8
    paths:
        - includes/
        - src/
    excludePaths:
        - '*/tests/*'
    ignoreErrors:
        # Exclude vendor if included
        - '#.*vendor.*#'

    plugins:
        - vendor/szepeviktor/phpstan-wordpress/extension.neon
EOF

# Run analysis
./vendor/bin/phpstan analyse

Output shows deprecated functions:

 2   Call to deprecated method create_function()
     /plugins/my-plugin/includes/callbacks.php:56
 5   Call to deprecated function get_post_meta()
     /plugins/my-plugin/src/post-handler.php:120

Grep-based search approach:

Search your codebase for known deprecated patterns:

# Find array access on objects
grep -r '\$object\[' includes/ src/

# Find ereg (completely removed in PHP 7.0)
grep -r 'ereg(' includes/

# Find mysql_ functions (removed in PHP 7.0)
grep -r 'mysql_' includes/

# Find split() (removed in PHP 7.0)
grep -r 'split(' includes/

# Find each() (removed in PHP 7.2)
grep -r '\beach(' includes/

# Find call_user_func_array without array check
grep -r 'call_user_func' includes/

WP HealthKit automated scanning:

WP HealthKit can analyze your plugin and identify:

- Deprecated PHP functions
- Deprecated WordPress functions
- Removed functions causing compatibility issues
- PHP 8.0+ incompatibilities
- Type declaration issues

The most comprehensive approach combines static analysis (PHPStan) with runtime testing (error logs) to catch both obvious deprecations and subtle compatibility issues.

WordPress-Specific Function Deprecations

Beyond PHP deprecations, WordPress itself deprecates functions. These are usually marked with _deprecated_function():

// WordPress deprecation example
function get_option_by_name($option_name) {
    _deprecated_function(__FUNCTION__, '4.5.0', 'get_option()');
    return get_option($option_name);
}

The deprecation notice tells you:

  • Which function is deprecated
  • When it was deprecated (WordPress version)
  • What to use instead

Common WordPress deprecations:

// Deprecated in 5.1, use rest_send_cors_headers()
do_action('rest_pre_dispatch');

// Deprecated in 5.5, use wp_get_current_user()
get_currentuserinfo();

// Deprecated in 5.2, use wp_die() with args array
wp_die('Error', 'Title', array('response' => 403));

// Deprecated in 5.0, use apply_filters()
apply_filters_deprecated('filter_name', array($value));

// Deprecated in 4.9, use wp_remote_post()
wp_remote_request($url, array('method' => 'POST'));

// Deprecated in 5.7, use wp_list_categories()
wp_dropdown_categories();

Check the WordPress.org plugin handbook for a comprehensive list: https://developer.wordpress.org/plugins/

WordPress deprecations are typically documented with migration paths in the handbook. The handbook entry for each deprecated function explains what changed, why it was deprecated, and what you should use instead. Always consult the official documentation rather than guessing about replacements.

Look for deprecation notices in your debug.log:

[18-Mar-2026 10:15:23 UTC] PHP Deprecated:  Plugin: 'my-plugin/my-plugin.php' is deprecated as of version 5.3.0! [Use register_block_type_args instead.](https://developer.wordpress.org/reference/functions/register_block_type_args/) in wp-includes/functions.php on line 4838

Planning Your Migration Strategy

Migrating deprecated code requires planning to avoid breaking existing functionality. Every function change carries risk—you might introduce a bug, change behavior in subtle ways, or create compatibility issues with integrations that depend on your plugin. Careful planning minimizes risk.

Start by inventorying all deprecated functions. Don't guess which ones are most important. Categorize by severity (critical functions vs. utility functions) and by effort (easy replacements vs. complex rewrites). Then prioritize—fix critical functions first, then utility functions, then the cleanup work. This way, if you run out of time or resources, you've at least fixed the most important issues.

Phase 1: Inventory and prioritize

// Create a migration checklist
/*
DEPRECATION MIGRATION CHECKLIST
================================

Priority 1 (Critical - breaks in PHP 8.0):
- [ ] Line 234: Array access on object $post (PHP 7.4)
- [ ] Line 456: mysql_* functions (PHP 7.0)
- [ ] Line 789: each() function (PHP 7.2)

Priority 2 (High - generates warnings):
- [ ] Line 123: get_currentuserinfo() deprecated in WP 5.5
- [ ] Line 345: wpautop() parameters changed in WP 5.5
- [ ] Line 567: do_action_ref_array() (use do_action with spread)

Priority 3 (Medium - forward compatibility):
- [ ] Line 678: Implicit nullable parameters (PHP 8.1)
- [ ] Line 890: Mixed type declarations (PHP 8.0)

Estimated effort:
- Priority 1: 4 hours
- Priority 2: 2 hours
- Priority 3: 1 hour
*/

Phase 2: Create a feature branch

git checkout -b migrate/php-deprecations

This isolates your changes so you can test thoroughly before merging.

Phase 3: Migrate incrementally

Don't change everything at once. Handle one deprecation category at a time:

# Commit 1: Replace all mysql_* functions
# Commit 2: Replace array access on objects
# Commit 3: Update WordPress function calls
# Commit 4: Update type declarations

This makes reviewing and debugging easier if something breaks.

Common PHP Deprecations and Solutions

Here are the most common deprecations and their solutions. These represent the patterns you'll encounter most frequently when modernizing legacy WordPress plugins. Understanding these patterns helps you recognize similar issues even when they appear in different contexts. Each solution demonstrates not just the replacement function but the reasoning behind why the old approach failed and why the new approach works better.

PHP 7.0: Removed Functions

The each(), ereg(), and mysql_* functions were completely removed in PHP 7.0. Code using them causes fatal errors immediately. These are high priority for migration because they make plugins completely non-functional on PHP 7.0+ servers.

Problem: Using each()

// Old code (PHP 5.x)
while ($item = each($array)) {
    echo $item['value'];
}

Solution: Use foreach()

// New code (PHP 7.2+)
foreach ($array as $value) {
    echo $value;
}

Problem: Using ereg() or eregi()

// Old code (PHP 5.x)
if (ereg('^[0-9]{3}-[0-9]{4}$', $phone)) {
    // Valid phone
}

Solution: Use preg_match()

// New code (PHP 7.0+)
if (preg_match('/^[0-9]{3}-[0-9]{4}$/', $phone)) {
    // Valid phone
}

Problem: Using mysql_* functions

// Old code (PHP 5.x)
$link = mysql_connect('localhost', 'user', 'pass');
mysql_select_db('db_name', $link);
$result = mysql_query('SELECT * FROM users', $link);

Solution: Use MySQLi or PDO

// New code (PHP 7.0+)
$link = mysqli_connect('localhost', 'user', 'pass', 'db_name');
$result = mysqli_query($link, 'SELECT * FROM users');

// Or use wpdb
global $wpdb;
$results = $wpdb->get_results('SELECT * FROM ' . $wpdb->users);

PHP 7.0: Deprecated Type Juggling

Problem: Assigning objects to array keys

// Old code
$key = new stdClass();
$key->id = 123;
$array[$key] = 'value'; // Object becomes array/string key

Solution: Extract scalar values

// New code
$key = 123;
$array[$key] = 'value';

// Or use arrays directly
$array['id_' . $object->id] = 'value';

PHP 7.0: Array Access on Non-Arrays

Problem: Array access on objects

// Old code
$post = get_post(123);
echo $post['post_title']; // $post is an object, not array

Solution: Use object property access

// New code
$post = get_post(123);
echo $post->post_title; // Correct object property access

PHP 7.4: Typed Properties

Problem: Implicit null typing

// PHP 7.3 (deprecated)
class Handler {
    public $value; // Could be null implicitly
}

Solution: Explicit typing

// PHP 7.4+ (correct)
class Handler {
    public ?string $value = null; // Explicitly nullable
    public int $count = 0;
}

PHP 8.0: Named Arguments

Problem: Positional arguments with many parameters

// Old code (hard to read)
wp_schedule_event(time(), 'daily', 'my_hook', array($param1, $param2));

Solution: Use named arguments

// New code (PHP 8.0+, clearer)
wp_schedule_event(
    time: time(),
    recurrence: 'daily',
    hook: 'my_hook',
    args: array($param1, $param2)
);

WordPress: Deprecated Admin Functions

Problem: Using removed admin functions

// Deprecated in WP 5.5
get_currentuserinfo(); // Populates global $current_user

// Deprecated in WP 5.2
wp_die('Error', 'Title', array('response' => 403));

Solution: Use modern WordPress functions

// WP 5.5+
$current_user = wp_get_current_user();
echo $current_user->display_name;

// WP 5.2+
wp_die(
    'Error message',
    'Page title',
    array(
        'response' => 403,
        'back_link' => true,
    )
);

Practical Tip: WP HealthKit scans your plugin code to identify these deprecated patterns automatically. Rather than manually searching your entire codebase, let automated analysis find the issues for you.

Let WP HealthKit identify deprecated functions in your plugin.

Automated Detection Tools

Automated tools make deprecation detection efficient and comprehensive. Finding deprecations manually is tedious and error-prone. You might miss obscure functions, incorrectly identify what's deprecated versus what's fine, or waste hours searching when a tool could do it in seconds. Automated tools handle this work reliably.

Tools like PHPStan and Rector are specifically designed to catch modern PHP patterns and identify deprecated usage. They understand the nuances—they know which functions are removed in which PHP versions, which WordPress functions are deprecated in which WordPress versions, and how to find these patterns in complex codebases. They can analyze thousands of lines of code in seconds and provide precise line numbers of problematic code.

PHPStan with WordPress support:

# Install in your plugin directory
composer require --dev \
    phpstan/phpstan \
    szepeviktor/phpstan-wordpress

# Create configuration
cat > phpstan.neon << 'EOF'
includes:
    - vendor/phpstan/phpstan/conf/config.level8.neon
    - vendor/szepeviktor/phpstan-wordpress/extension.neon

parameters:
    level: 8
    paths:
        - src/
        - includes/
        - my-plugin.php
    excludePaths:
        - '*/vendor/*'
        - '*/tests/*'
EOF

# Run analysis
./vendor/bin/phpstan analyze

# Output shows all deprecations:
 3	Call to deprecated function wp_get_post_terms()

PHP Mess Detector (PHPMD):

# Install PHPMD
composer require --dev phpmd/phpmd

# Analyze code
./vendor/bin/phpmd src,includes text cleancode,codesize,design,naming,unusedcode --extensions=php

Rector for automated refactoring:

Rector can automatically fix some deprecations:

# Install Rector
composer require --dev rector/rector rector/rector-wordpress

# Preview changes
./vendor/bin/rector process src --dry-run

# Apply changes
./vendor/bin/rector process src

Rector includes rules for WordPress deprecations:

// Automatically fixes these patterns
get_currentuserinfo() → wp_get_current_user()
create_function() → Use closure instead
wp_register_sidebar_widget() → register_widget()

Testing After Migration

Migration carries risks. Testing is essential to ensure nothing breaks.

Unit tests:

// tests/test-migration.php

class DeprecationMigrationTests extends WP_UnitTestCase {
    
    public function test_post_object_access() {
        $post = get_post(1);
        
        // Should work with object notation
        $this->assertNotEmpty($post->post_title);
        $this->assertNotEmpty($post->post_content);
    }
    
    public function test_user_functions_work() {
        wp_set_current_user(1);
        
        // New function works
        $user = wp_get_current_user();
        $this->assertNotEmpty($user->display_name);
    }
    
    public function test_regex_migration() {
        // Old ereg pattern
        $this->assertTrue(
            preg_match('/^[0-9]+$/', '12345')
        );
        
        // Verify it matches same strings as old code
        $this->assertFalse(
            preg_match('/^[0-9]+$/', 'abc123')
        );
    }
}

Functional tests:

Test actual user workflows with the new code:

# Test on PHP 7.4
php7.4 -S localhost:8000 &
# Run tests manually, verify features work

# Test on PHP 8.0
php8.0 -S localhost:8000 &
# Run tests again

# Test on PHP 8.1
php8.1 -S localhost:8000 &
# Run tests again

Automated test matrix:

Use GitHub Actions to test on multiple PHP versions:

# .github/workflows/test.yml
name: Tests

on: [push, pull_request]

jobs:
  test:
    runs-on: ubuntu-latest
    strategy:
      matrix:
        php-version: ['7.4', '8.0', '8.1', '8.2']
        wordpress-version: ['6.0', '6.1', '6.2']
    
    steps:
      - uses: actions/checkout@v3
      
      - uses: shivammathur/setup-php@v2
        with:
          php-version: ${{ matrix.php-version }}
      
      - run: composer install
      - run: ./vendor/bin/phpunit
      - run: ./vendor/bin/phpstan analyse

Regression testing:

Create a checklist of features to test manually. Regression testing means testing that old functionality still works after your changes. The risk is that you fixed one deprecated function but broke something that depends on it. By systematically testing core features, WordPress integration points, error handling, and performance, you gain confidence that the changes didn't introduce problems.

Automated tests (unit tests, integration tests) should verify that specific functions work correctly. But manual regression testing verifies that the plugin works from a user perspective. A test might pass technically but the feature might feel broken because of performance degradation or subtle behavior changes.

Feature Testing Checklist
==========================

Core Plugin Features:
- [ ] Plugin activates without errors
- [ ] Settings page loads and saves
- [ ] Main feature works (e.g., import functionality)
- [ ] Export functionality produces valid files
- [ ] API endpoints respond correctly

WordPress Integration:
- [ ] Hooks and filters work correctly
- [ ] Custom post types display
- [ ] Shortcodes render properly
- [ ] Admin menus appear
- [ ] Capabilities check works

Error Handling:
- [ ] No PHP warnings in debug.log
- [ ] No PHP notices in debug.log
- [ ] No jQuery deprecation warnings
- [ ] Graceful error messages shown

Performance:
- [ ] Page load times haven't regressed
- [ ] Database queries are reasonable
- [ ] Memory usage is acceptable

Additional Resources

Frequently Asked Questions

What if I find deprecated code I didn't write?

You inherited it from a previous developer. It's your responsibility now. Create a migration plan and schedule time to fix it. Modern hosting won't run your plugin if it uses removed functions. The longer you wait, the more painful it becomes. By the time PHP version X+2 is mainstream, fixing PHP version X deprecations becomes urgent. Users complain. Plugin ratings drop. You're forced to fix it quickly under pressure, leading to bugs.

The best approach is proactive maintenance. When you discover deprecated code, fix it as part of your regular development. Don't accumulate technical debt hoping someone else will handle it later. That "later" never comes until crisis hits.

Can I use a compatibility shim for deprecated functions?

Sometimes. You can create a polyfill for a deprecated function:

// If WordPress removed get_currentuserinfo(), polyfill it
if (!function_exists('get_currentuserinfo')) {
    function get_currentuserinfo() {
        global $current_user;
        $current_user = wp_get_current_user();
    }
}

But this just delays the problem. Better to migrate properly.

How much time should I allocate for deprecation migration?

Depends on plugin size and age:

  • Small, modern plugin: 2-4 hours
  • Medium plugin: 1-2 days
  • Large legacy plugin: 1-2 weeks

Use automated detection (PHPStan, Rector) to reduce manual work. The time investment is worth it compared to the cost of a production incident where users can't use your plugin because it crashes on modern PHP versions. Prevention is far cheaper than emergency fixes. Additionally, the migration process teaches you about modern PHP patterns and best practices, improving your skills as a developer.

Should I create a major version bump for deprecation fixes?

Only if there are breaking changes for users. Deprecation migration is usually backward compatible and warrants a minor version bump (e.g., 2.0.0 → 2.1.0).

What if my WordPress version doesn't support the new syntax?

Use minimum WordPress version that supports it:

// WordPress 5.7+
if (function_exists('wp_new_function')) {
    wp_new_function();
} else {
    // Fallback for older WordPress
    old_function();
}

But ideally, drop support for ancient WordPress versions.

Is it worth migrating if I'm thinking of sunsetting the plugin?

If you're planning to stop maintenance, maybe not. But if you want to keep it working, migration is essential. Deprecated code will eventually break.

Can I use both old and new syntax during transition?

Yes, temporarily. But don't leave both active indefinitely—it's confusing and unmaintainable. After testing, remove the old code completely.

Conclusion

WordPress plugin PHP deprecated functions migration isn't exciting, but it's essential maintenance. Ignoring deprecations guarantees that your plugin will eventually break when hosting environments upgrade to newer PHP versions. The question isn't whether you'll migrate, but when—before users complain or after they've already switched to competitors.

By systematically identifying deprecated code, planning migration carefully, testing thoroughly, and using automated tools, you can modernize your plugin without breaking functionality. The effort pays off in compatibility, performance, and maintainability.

Think of deprecation migration as preventive maintenance. You wouldn't wait for your car's engine to fail before changing the oil—you do it proactively. Same with deprecated code. Regular, proactive maintenance prevents emergencies. A few hours of work now saves days of crisis-mode debugging later.

The best plugins are modernized regularly. They track WordPress updates, PHP updates, and coding standard evolution. Their developers run static analysis regularly, fix warnings promptly, and test against newer environments. These plugins work reliably on modern hosting, perform better than legacy competitors, and attract users who appreciate quality and reliability.

WP HealthKit helps you identify deprecated functions and compatibility issues automatically. Rather than manually searching your codebase, get a comprehensive report of what needs migration. Our scanning service analyzes your entire plugin, identifies all deprecated functions, categorizes them by severity, and provides migration guidance. This transforms a potentially overwhelming task into a manageable, prioritized action list.

Upload your plugin to WP HealthKit for automated deprecation detection and migration guidance.

For more on WordPress plugin quality and modernization, check out our guides on PHP 8 compatibility for WordPress plugins and PHPStan static analysis for WordPress. Keeping your plugin modern and compatible is an ongoing process that pays dividends in user satisfaction and plugin longevity.

Ready to audit your plugin?

WP HealthKit checks for all the issues in this article and 40+ more across 49 verification layers.

Comments

WordPress Plugin PHP Deprecation: A Full Migration Guide | WP HealthKit