How to Know What Breaks Before You Upgrade WordPress to PHP 8.4
DEV Community

How to Know What Breaks Before You Upgrade WordPress to PHP 8.4

Every WordPress developer knows the feeling. A host emails: "PHP 7.4 reaches end of life - we're moving you to 8.x." Or you finally want the performance and security of PHP 8.4. You stage it, click upgrade, and… white screen. Somewhere in the 40 plugins and 3 themes on the site, something called a function PHP removed years ago - and now the whole site is down.

The frustrating part: the broken code is almost never yours. It's buried in third-party plugins and themes you didn't write and can't easily read. So how do you find out what breaks before you upgrade, instead of after? This post walks through exactly that, using an open-source tool called Pressready.

Why "just test it on staging" isn't enough

Staging tells you that something broke, rarely what or where - and only for the code paths you happen to exercise. A fatal in an admin screen or a checkout edge case you didn't click won't surface until a real user hits it. You need something that reads all the code statically and reports every risky symbol, whether or not that path runs during your manual test. That's a job for static analysis across the whole stack.

Two kinds of "breakage": PHP and WordPress

Upgrades break sites along two axes, and a good audit covers both:

  • The PHP axis - language features that get removed (e.g. create_function() is gone in PHP 8.0, each() in 8.0) or change behaviour between versions.
  • The WordPress axis - core APIs that WordPress deprecates or removes from one release to the next.

Pressready checks both in a single pass: it runs PHPCompatibility for the PHP axis and a custom PHP_CodeSniffer sniff - driven by a generated dataset of WordPress core deprecations - for the WordPress axis.

Install it (pick whatever fits your setup)

No Composer in the project? Use the standalone PHAR or Docker:

# Standalone PHAR - single self-contained file, just needs PHP
curl -L https://github.com/itzmekhokan/pressready/releases/latest/download/pressready.phar -o pressready.phar
chmod +x pressready.phar

# Or Docker - nothing to install at all
docker run --rm -v "$PWD":/src -w /src ghcr.io/itzmekhokan/pressready:1 --php=8.4 --path=wp-content

# Or Homebrew
brew tap itzmekhokan/pressready && brew install pressready

Prefer it as a project dev dependency?

composer require --dev itzmekhokan/pressready

Run your first scan

Point it at wp-content and tell it the PHP (and optionally WordPress) version you're targeting:

vendor/bin/pressready --php=8.4 --wp=6.9 --path=wp-content

You get a report grouped by component (plugin/theme), with a file:line and a severity for every finding:

βœ— FATAL (1) - these break on upgrade; fix first:
  wp-content/plugins/legacy-forms/forms.php:88
    Function create_function() - removed PHP 8.0

⚠ RISKY (3) - review the behaviour changes before upgrading
  …

Reading the severity model

Pressready grades findings so you can triage instead of drowning in noise:

Severity What it means
fatal A symbol the target version removed - this white-screens on upgrade. Fix first.
risky Behaviour changed but still runs; may produce wrong results.
php / wp Deprecated (still works for now). Clear at your leisure.

The mental model: fix every fatal before you upgrade, schedule the risky ones, and burn down deprecations over time.

The question you actually have: "how far can I safely go?"

Most upgrade decisions aren't "does PHP 8.4 break this?" - they're "how far can I move right now, and what's the first thing that stops me?" That's what --matrix answers, grading every version in a range from a single scan:

vendor/bin/pressready --php=7.4-8.4 --matrix --path=wp-content

PHP 7.4  βœ“ clear
8.0      βœ— 1 fatal
8.1      βœ— 1 fatal
…

Safe through PHP 7.4 Β· first break: PHP 8.0

Now you know: this site can't move past 7.4 until that one plugin is fixed - and you know exactly which one.

Adopting it on a messy legacy site

Inheriting a site with hundreds of pre-existing warnings? Don't try to fix them all on day one. Snapshot the current state as a baseline and only fail on new problems going forward:

vendor/bin/pressready --php=8.4 --generate-baseline

# later, in CI:
vendor/bin/pressready --php=8.4 --baseline --fail-on=fatal

Put it in CI so it never regresses

Pressready is built to gate pull requests. A whole GitHub Actions check is two lines:

- uses: actions/checkout@v4
- uses: itzmekhokan/pressready@v1
  with:
    php: "8.4"
    wp: "6.9"
    fail-on: fatal

It also speaks SARIF (GitHub code scanning), a GitLab Code Quality report, and runs under Bitbucket, Jenkins, pre-commit, or wp pressready via WP-CLI - same engine everywhere.

Honest limitations

It's static analysis, so it catches symbol-level removals and deprecations across the stack - not runtime logic regressions or data issues. PHP 8.2–8.4 detection rides on a pre-release of PHPCompatibility (a one-time opt-in during install). And the WordPress dataset is only as current as its last regeneration - it warns you on stderr if you target a newer WordPress than it knows about. For "is this site safe to move to PHP 8.4," though, it covers the scary 90% that actually takes sites down.

Wrapping up

PHP upgrades don't have to be a roll of the dice. Scanning the whole stack first turns "let's hope" into a concrete punch list: here are the fatals, here's the plugin causing them, here's how far you can safely go today.

Pressready is free and open source (GPL-2.0). If you try it on a real site, I'd love to hear what it caught - and what you wish it caught that it doesn't yet.

Comments

No comments yet. Start the discussion.