I was called in to fix a custom analytics plugin on a client’s site. It was a mess. The original developer had left, and the client wanted a “simple” change: track different events for logged-in users versus guests. The trouble was that the whole plugin was one giant class with every method declared as static. It was a textbook example of how to misuse the WordPress static keyword.
Every event was tracked with a call like Analytics_Plugin::track_event('page_view'). To tell whether a user was logged in, I’d have to litter that track_event method with conditional logic. It was already a 200-line monster, and this would only make it worse. It’s procedural code hiding inside a class wrapper.
Why your static methods are a ticking time bomb
The static keyword isn’t the enemy. It has its uses. But in WordPress, developers often lean on it as a crutch to avoid real object-oriented programming. They spin up a “Utilities” or “Helpers” class and dump everything in there. As a good post over at carlalexander.ca points out, WordPress has a long procedural history, so this feels like a natural move.
My first thought was to just hack it: add a check inside track_event() like if (is_user_logged_in()) { ... }. And yeah, it would have worked, for now. But it’s a bad fix. It piles complexity onto a method that has no business knowing about user state. The underlying problem is that the method is static: it can’t hold any state of its own, so you end up reaching for global state instead. A nightmare to maintain.
A static method should be stateless. Give it the same input and it returns the same output every time. It shouldn’t care whether a user is logged in, what time it is, or anything else about the current state of the app. Break that rule and you get code that’s impossible to test and a pain to maintain.
<?php
// The better, object-oriented way
class AnalyticsTracker {
private $is_user_logged_in;
public function __construct() {
$this->is_user_logged_in = is_user_logged_in();
}
public function track_event(string $event_name) {
$event_data = ['name' => $event_name];
if ($this->is_user_logged_in) {
$event_data['user_id'] = get_current_user_id();
}
// Send this data to your analytics service...
// error_log(print_r($event_data, true));
}
}
// Now the call is contextual
$tracker = new AnalyticsTracker();
$tracker->track_event('page_view');
So, what’s the real fix?
The fix is to think in objects. Instead of a static class, I refactored it into a proper AnalyticsTracker class. When I need to track something, I instantiate it. The constructor checks whether the user is logged in and stores that in a private property. The track_event method can then read that internal state ($this->is_user_logged_in) to decide how to behave. The result is clean, testable, and no longer fighting the way OOP works.
- Static methods are for stateless helpers. Think of a function that sanitizes a string and needs to know nothing else. That’s a perfect use for
static. - Objects are for managing state. When a method’s behavior has to change based on something like user status, that logic belongs in an object that holds the state.
This stuff gets complicated fast. If you’re tired of debugging someone else’s mess and just want your site to work, drop my team a line. We’ve probably seen it before.
Stop treating classes like folders for your functions. Using the WordPress static keyword well comes down to a mindset shift, from procedural hacks toward proper object-oriented design. Your future self will thank you.