I got a call from a client last week. Their last developer bailed, and they had a “simple” request: add a new delivery option to their custom plugin’s settings page. Should’ve been a 30-minute job. Then I opened the plugin file. It was a single, 2,000-line procedural PHP file, and the admin page was a spaghetti-monster function right in the middle of it. Total mess.
This is the kind of technical debt that grinds projects to a halt. When you mix your registration logic, your data handling, and your HTML rendering all in one place, you create a house of cards. You can’t change one thing without breaking three others. The only sane way forward is to refactor it properly with a WordPress admin page class.
Stop Mixing Everything Together
My first thought was to just find the right spot in that mess and jam the new code in. Get it done, get paid. But I couldn’t do it. Trying to add the new fields felt like performing surgery with a sledgehammer. Every variable was global, the form processing was mixed in with the HTML, and there was zero separation of concerns. It was a classic example of how not to build a plugin.
The real fix is to treat the admin page like an object. It has a job to do, and that job can be broken down into distinct tasks: registering itself with WordPress, handling its settings, and rendering the HTML. This approach builds on some great foundational ideas about WordPress OOP I first saw over at carlalexander.ca. By creating a class, you give each of these tasks its own dedicated method. Clean. Maintainable. Professional.
A Practical WordPress Admin Page Class
Instead of one giant function, you create a class that neatly organizes everything. You have methods for getting the page title, the menu slug, and the required capability. Then, you have methods for registering your settings and fields with the Settings API. Finally, you have a render method that does one thing: includes a template file. Here’s the kicker: the logic is separate from the presentation.
<?php
class MyPlugin_AdminPage
{
/**
* The unique slug for this admin page.
* @var string
*/
private $slug = 'my-plugin-settings';
/**
* Register the admin page with WordPress.
*/
public function register()
{
add_options_page(
'My Plugin Settings',
'My Plugin',
'manage_options',
$this->slug,
array($this, 'render_page')
);
add_action('admin_init', array($this, 'register_settings'));
}
/**
* Register the settings and fields.
*/
public function register_settings()
{
register_setting($this->slug, 'myplugin_option_1');
add_settings_section(
$this->slug . '-section',
'Main Settings',
null,
$this->slug
);
add_settings_field(
'myplugin_option_1',
'My First Option',
array($this, 'render_option_field'),
$this->slug,
$this->slug . '-section'
);
}
/**
* Render the actual admin page.
*/
public function render_page()
{
// Use a separate PHP template file for the HTML.
// This keeps your class clean.
include plugin_dir_path(__FILE__) . 'templates/admin-page.php';
}
/**
* Render a settings field.
*/
public function render_option_field()
{
$option_value = get_option('myplugin_option_1', '');
echo '<input type="text" name="myplugin_option_1" value="' . esc_attr($option_value) . '" />';
}
}
// How to use it:
$admin_page = new MyPlugin_AdminPage();
add_action('admin_menu', array($admin_page, 'register'));
So, What’s the Point?
Look, you could just hack it together in the main plugin file. It might even work. For now. But when the client comes back in six months with another “simple” request, you’ll be back in that same spaghetti code, and the job will take ten times as long. This isn’t about writing more code; it’s about writing smarter, more organized code.
- It’s Maintainable: When you need to change the page title, you go to the `get_page_title` method. Simple. No more hunting through a 2,000-line file.
- It’s Reusable: You can create a base admin page class and extend it for different plugins, saving yourself a ton of time down the road.
- It’s Professional: This is how you build plugins that don’t become a nightmare for the next developer. Trust me on this, they’ll thank you for it.
Look, 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.
Leave a Reply