“Non-static method … cannot be called statically” on PHP 8: what it means and the fix

By CompatNav · Published · Last reviewed · 3 min read

Short answer

It’s a fatal error from PHP 8.0 and later: a plugin or theme calls one of its methods as Class_Name::method(), but the method isn’t declared static, so it needs an object to run on. PHP 7.4 accepted it with a deprecation notice (“should not be called statically”), which WordPress doesn’t report while WP_DEBUG is off; PHP 8 removed that possibility, and the page stops. Update the plugin or theme, or send the message to its developer. The developer fix is to declare the method static, or to call it on an object.

The message, on PHP 7.4 and PHP 8

A price helper formats amounts with a method called as Price_Tools::format(), a habit from older PHP code. The method isn’t declared static:

wp-content/plugins/price-tools/price-tools.php

<?php
class Price_Tools {
    public function format($amount) {
        return '$' . number_format($amount, 2);
    }
}

echo Price_Tools::format(19.9), "\n";

Output on PHP 7.4.33

Deprecated: Non-static method Price_Tools::format() should not be called statically in /var/www/html/wp-content/plugins/price-tools/price-tools.php on line 8
$19.90

Output on PHP 8.0.30the script stopped

Fatal error: Uncaught Error: Non-static method Price_Tools::format() cannot be called statically in /var/www/html/wp-content/plugins/price-tools/price-tools.php:8
Stack trace:
#0 {main}
  thrown in /var/www/html/wp-content/plugins/price-tools/price-tools.php on line 8

PHP 7.4 runs it and adds a deprecation notice. PHP 8.0 stops at the call. php.net, in the PHP 8.0 changes: “The ability to call non-static methods statically has been removed.” (php.net)

What it means

A class method is either static, called on the class itself (Price_Tools::format()), or non-static, called on an object made from the class ($tools->format()). Old PHP versions let code call a non-static method the static way, as long as the method didn’t use $this. PHP 8 doesn’t: the method must be declared static to be called on the class.

Through a WordPress hook: a different wording

Plugins often register a method on a hook as a text, add_action( 'init', 'My_Plugin::setup' ). If that method isn’t static, PHP 8 stops when WordPress runs the hook, with a longer message, because WordPress calls the method through call_user_func_array():

wp-content/plugins/my-plugin/my-plugin.php

<?php
class My_Plugin {
    public function setup() {
        echo "Setup done\n";
    }
}

// The plugin registered 'My_Plugin::setup' on a hook; when the hook runs,
// WordPress calls it like this (wp-includes/class-wp-hook.php):
call_user_func_array('My_Plugin::setup', []);

Output on PHP 7.4.33

Deprecated: Non-static method My_Plugin::setup() should not be called statically in /var/www/html/wp-content/plugins/my-plugin/my-plugin.php on line 10
Setup done

Output on PHP 8.0.30the script stopped

Fatal error: Uncaught TypeError: call_user_func_array(): Argument #1 ($callback) must be a valid callback, non-static method My_Plugin::setup() cannot be called statically in /var/www/html/wp-content/plugins/my-plugin/my-plugin.php:10
Stack trace:
#0 {main}
  thrown in /var/www/html/wp-content/plugins/my-plugin/my-plugin.php on line 10

On a real site, this message points to wp-includes/class-wp-hook.php, the file where WordPress runs hooks. WordPress isn’t the cause: the method named in the message, My_Plugin::setup(), tells you which plugin is.

Why you didn’t see it coming

PHP 7.4 did warn, with a deprecation notice. But while WP_DEBUG is off, WordPress doesn’t report deprecation notices (WordPress 7.1.2 source), so on a normal live site the warning was never written anywhere.

Fix it, in order

  1. Site down? Switch PHP back or pause the plugin: the critical error guide.
  2. Find the plugin or theme from the path in the message, or from the class name.
  3. Update it (Dashboard → Updates).
  4. Already up to date? Send the full message to its developer. If the plugin hasn’t been updated in years, look for a maintained alternative.

Find it before you switch

CompatNav doesn’t check for this pattern: our scan of the example above found nothing. Your PHP 7.4 site can tell you, though: set WP_DEBUG and WP_DEBUG_LOG to true, with WP_DEBUG_DISPLAY false (the WordPress debug log), use the site for a while, and search the log for “should not be called statically”. Each line is a fatal error on PHP 8. Other PHP 8.0 changes that stop old code: create_function(), each(), old-style constructors, all of which CompatNav does find.

Key takeaways

  • PHP 7.4: “Deprecated: Non-static method … should not be called statically”, and the code ran.
  • PHP 8.0 and later: “Uncaught Error: Non-static method … cannot be called statically”, and the page stops.
  • WordPress doesn’t report deprecation notices while WP_DEBUG is off, so on a live site the warning sign stayed invisible.
  • Through a WordPress hook, PHP 8 words it “call_user_func_array(): Argument #1 ($callback) must be a valid callback, non-static method … cannot be called statically”.
  • The developer fix: add static to the method, or call it on an object.

Frequently asked questions

Why did it work on PHP 7.4?

PHP 7.4 still allowed it, with a deprecation notice. php.net lists the change for PHP 8.0: the ability to call non-static methods statically has been removed.

Can I fix it myself?

Not in a plugin or theme you don’t maintain: an update would undo the change. Switch PHP back if the site is down, update the plugin, and send the message to its developer. In your own code, see the fix below.

Does WordPress itself cause this?

No. WordPress calls what a plugin registers. If a plugin registers 'My_Class::method' as a hook callback and that method isn’t static, PHP 8 stops when WordPress runs the hook; the plugin is the one to fix.

Check your own site before you upgrade

CompatNav is a free WordPress plugin. It reads the code of your plugins and themes on your own server and tells you, in plain words, what will break and what will only show notices on the PHP version you choose. It never changes your code. It can’t see problems that only appear while code runs with real data, so a quick check of your site after the upgrade still matters.

Get CompatNav on wordpress.org How it works

Sources

About the code examples: each output is the real output of the code shown, run with the official PHP builds, without a php.ini, with all errors reported and displayed. Only the file path was replaced by a neutral server path.