Why a simple WordPress plugin edit broke everything

A client came to us a few weeks back with a simple request: “Can you add a new size option to our meme shortcode plugin?” Sounds easy. Then I opened the plugin file and found a single 2,000-line PHP class. Everything lived in there: the shortcode logic, the admin page, the database options, the CSS injection. A total mess.

Changing one thing felt like defusing a bomb. You touch one function and you have no idea what else it might break. That is a classic symptom of violating the WordPress single responsibility principle, and it is why a five-minute job turns into a five-hour headache.

Why we end up with these monster classes

It is not always the developer’s fault. The official WordPress documentation practically pushes you to dump everything into one class to avoid function name collisions. If you are moving from procedural code to OOP, that looks like the logical next step. It just does not scale.

My first instinct was to just hack the new size option in. Add another property, another ‘if’ statement, and call it done. And it would have worked, right up until the next “simple” request landed. The fix had to be structural. The whole thing needed a refactor.

Applying the WordPress single responsibility principle

The single responsibility principle is the ‘S’ in SOLID. A class should have one job and only one. A class that handles shortcodes should not also render an admin page. This is a pragmatic take on a breakdown I first read on carlalexander.ca, and in practice it holds up.

Instead of one giant file, we split the plugin into classes with clear responsibilities.

  • Plugin.php: the main entry point. Its only job is to load the other components.
  • Options.php: handles all interaction with the database, getting and setting options, and nothing else.
  • AdminPage.php: renders the settings page in the WordPress admin.
  • Shortcode.php: registers the shortcode and builds its output.

When each class has a single job, the code becomes predictable. The Shortcode class, for example, stays clean and focused.

namespace WPMemeShortcode;

class Shortcode
{
    /**
     * @var Options
     */
    private $options;

    /**
     * Constructor.
     *
     * @param Options $options
     */
    public function __construct(Options $options)
    {
        $this->options = $options;
    }

    /**
     * Handles the output of the shortcode.
     *
     * @param array  $attributes
     * @param string $content
     */
    public function handle(array $attributes, $content = null)
    {
        // Do nothing if no ID is given or it is not numeric
        if (!isset($attributes['id']) || !is_numeric($attributes['id'])) {
            return $content;
        }

        // If no size is given, get the default.
        if (!isset($attributes['size']) || !is_numeric($attributes['size'])) {
            $attributes['size'] = $this->options->get('size', '500');
        }

        return "<img src=\"http://cdn.memegenerator.net/instances/{$attributes['size']}x/{$attributes['id']}.jpg\" />";
    }
}

So what’s the payoff?

You might wonder if this is worth the trouble on a small plugin. It is. The point is writing code that you, or the next developer, can actually work with six months from now.

  • It is clearer: no more guessing where a function lives. The class name tells you its job.
  • It is easier to change: need to change how options are saved? You edit one file, the Options class, not ten different places.
  • It is testable: writing unit tests for a class that does one thing is far easier than for a class that does everything.

This stuff gets complicated fast. If you are tired of debugging someone else’s mess and just want your site to work, drop my team a line. We have probably seen it before.

author avatar
Ahmad Wael
I'm a WordPress and WooCommerce developer with 15+ years of experience building custom e-commerce solutions and plugins. I specialize in PHP development, following WordPress coding standards to deliver clean, maintainable code. Currently, I'm exploring AI and e-commerce by building multi-agent systems and SaaS products that integrate technologies like Google Gemini API with WordPress platforms, approaching every project with a commitment to performance, security, and exceptional user experience.