Wrap the WordPress Options API in one class

I took over a legacy WooCommerce plugin for a new client last month, and it was a mess. The previous developer had sprinkled get_option() and update_option() calls everywhere. Some option names had the plugin’s prefix, some didn’t, and one clashed with an entirely different plugin, which made settings reset at random. The client was frustrated that their “save settings” button was basically a roll of the dice, and so was I.

My first thought was a global find-and-replace: hunt down every instance of get_option and slap the proper prefix on it. Quick and dirty, and yeah, it would have fixed the immediate bug. But it was a patch over the real problem, not a fix for the architecture. The next developer, or me at 2 AM on a deadline, would make the same mistake again. The fix had to go deeper.

A wrapper class for the WordPress Options API

Stop calling the WordPress Options API functions directly. For any plugin of real size, doing so is asking for trouble. Instead, create a simple “gatekeeper” class that handles all the interactions for you. It’s the only part of your plugin that should be allowed to talk to the options table.

The good news is that it’s not much work. You’re creating a simple wrapper that enforces your rules automatically, such as making sure every option key is prefixed correctly. This is a stripped-down version of a fuller design pattern for the options API, an idea I first saw laid out at carlalexander.ca.

<?php

/**
 * Manages plugin options with a consistent prefix.
 */
class MyPlugin_Options
{
    private $prefix = 'my_plugin_';

    /**
     * Gets a prefixed option from the database.
     *
     * @param string $name The option name, without prefix.
     * @param mixed $default The default value.
     * @return mixed
     */
    public function get($name, $default = null)
    {
        return get_option($this->prefix . $name, $default);
    }

    /**
     * Sets a prefixed option in the database.
     *
     * @param string $name The option name, without prefix.
     * @param mixed $value The value to set.
     */
    public function set($name, $value)
    {
        update_option($this->prefix . $name, $value);
    }

    /**
     * Removes a prefixed option from the database.
     *
     * @param string $name The option name, without prefix.
     */
    public function remove($name)
    {
        delete_option($this->prefix . $name);
    }
}

// Now, instead of this scattered everywhere:
// update_option('my_plugin_api_key', 'some_value');

// You do this through your gatekeeper:
// $options = new MyPlugin_Options();
// $options->set('api_key', 'some_value');

Why this works

By routing every call through this class, you fix the problem at its source. You can’t “forget” the prefix because the class adds it. You can’t get a typo in the option name across 15 different files, because you define it once. You’re building guardrails that make the right thing easy and the wrong thing hard.

  • Stop scattering raw get_option and update_option calls through your plugin. That’s what causes this kind of mess.
  • A wrapper class keeps the logic in one place. It’s about ten minutes of work that saves hours of debugging later.
  • The prefix gets enforced automatically, so there’s no more guesswork or naming conflicts.
  • The codebase gets cleaner and more predictable to work in.

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.

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.