Mahamudul Hasan Rubel
HomeAboutProjectsSkillsExperienceBlogCoursesPhotosContact
Mahamudul Hasan Rubel

Senior Software Engineer crafting high-performance web applications and SaaS platforms.

Navigation

  • Home
  • About
  • Projects
  • Skills
  • Experience
  • Blog
  • Courses
  • Photos
  • Contact

Get in Touch

Available for senior/lead roles and consulting.

bd.mhrubel@gmail.comHire Me

© 2026 Mahamudul Hasan Rubel. All rights reserved.

Built with using Next.js 16 & Tailwind v4

Back to Blog
Lesson 9 of the WordPress Plugin Development: Foundations (PHP & MVC) course
WordPressJune 25, 20263 min read

The Controller Layer for Admin Pages: WordPress MVC Mastery

Learn how to implement a Controller layer for WordPress admin pages. Separate your UI and business logic to maintain a scalable, professional plugin architecture.

WordPressPHPMVCArchitectureRefactoringAdminplugin-development

Previously in this course, we explored the Creating Admin Menus lesson. While that lesson showed you how to register menus using simple callback functions, dumping all your HTML and business logic into the main plugin file will quickly lead to a "spaghetti code" nightmare as your Knowledge Base project grows.

In this lesson, we will implement the Controller layer of our MVC architecture. By shifting admin logic into a dedicated class, we ensure our main plugin file stays slim, readable, and focused solely on bootstrapping our services.

Why use a Controller?

In the context of WordPress, a controller is a class responsible for handling requests from the admin dashboard and returning the appropriate response (usually a rendered view).

When you follow the Designing for MVC in WordPress approach, you stop treating your main plugin file as a dumping ground for logic. Instead, you treat it like an orchestrator. Your main plugin class initializes your controllers, and your controllers handle the "how" of your admin pages.

Creating the AdminController

To keep our architecture clean, create a new file: app/Controllers/AdminController.php. This class will contain the logic previously handled by anonymous functions or global procedural callbacks.

PHP
namespace KnowledgeBase\Controllers;

class AdminController {
    #6A9955">/**
     * Renders the main dashboard page for the Knowledge Base.
     */
    public function renderDashboard() {
        #6A9955">// In a real-world scenario, you might pass data from a Model here.
        echo '<div class="wrap"><h1>Knowledge Base Dashboard</h1><p>Welcome to your KB admin area.</p></div>';
    }

    #6A9955">/**
     * Handles the submenu page rendering.
     */
    public function renderSettings() {
        echo '<div class="wrap"><h1>KB Settings</h1><p>Configure your plugin here.</p></div>';
    }
}

Routing Requests to Controller Methods

Now that we have a controller, we need to wire it into the WordPress menu system. We do this inside our main plugin class, which we established in Defining the Plugin Core Class.

Instead of passing a simple function name to add_menu_page, we pass an array containing our controller instance and the method name: [$this->adminController, 'renderDashboard'].

PHP
namespace KnowledgeBase;

use KnowledgeBase\Controllers\AdminController;

class Plugin {
    protected $adminController;

    public function __construct() {
        $this->adminController = new AdminController();
        add_action('admin_menu', [$this, 'registerAdminMenus']);
    }

    public function registerAdminMenus() {
        add_menu_page(
            'Knowledge Base',
            'Knowledge Base',
            'manage_options',
            'kb-dashboard',
            [$this->adminController, 'renderDashboard'], #6A9955">// Routing here
            'dashicons-book'
        );

        add_submenu_page(
            'kb-dashboard',
            'Settings',
            'Settings',
            'manage_options',
            'kb-settings',
            [$this->adminController, 'renderSettings']
        );
    }
}

Hands-on Exercise: Refactor Your Menu

  1. Create the app/Controllers/AdminController.php file in your plugin directory.
  2. Move your existing menu callback logic from your main plugin file into the AdminController methods.
  3. Update your registerAdminMenus method in the main plugin class to use the array syntax ([$this->adminController, 'methodName']) to point to your new controller.
  4. Refresh your WordPress dashboard to ensure the menus still render correctly.

Common Pitfalls

  • Namespace Mismatches: Ensure your AdminController has the correct namespace and that your autoloader is correctly mapping the app/ directory. If you get a "callable not found" error, double-check your class loading.
  • Dependency Bloat: Do not put database queries directly in your AdminController. If you need to fetch data, follow the Laravel Repository Pattern logic: keep the controller thin and delegate data retrieval to a Model or Service layer.
  • Hardcoding Views: Eventually, you should move the HTML strings out of the controller and into dedicated template files (we will cover this in later lessons). For now, keeping them in the controller is a step up from the main plugin file, but keep the HTML minimal.

Recap

By introducing a controller, we have successfully decoupled our menu registration logic from our UI rendering logic. Your main plugin class is now responsible only for "hooking" things up, while the AdminController owns the execution of admin-facing requests. This separation of concerns is the bedrock of maintainable WordPress development.

Up next: We will move beyond static menus and start interacting with the database by Registering Custom Post Types for our Knowledge Base articles.

Previous lessonCreating Admin MenusNext lesson Registering Custom Post Types
Back to Blog

Similar Posts

WordPressArchitectureJune 25, 20263 min read

Designing for MVC in WordPress: Professional Plugin Architecture

Learn to organize your WordPress plugin using the MVC pattern. Master directory structures, class loading, and separation of concerns for scalable code.

Read more
WordPressWordPressJune 25, 2026

Part of the course

WordPress Plugin Development: Foundations (PHP & MVC)

beginner · Lesson 9 of 47

  1. 1

    Plugin Anatomy and File Structure

    3 min
  2. 2

    The Plugin Lifecycle Hooks

    4 min
  3. 3

    Designing for MVC in WordPress

    3 min
3 min read

REST API Integration: Exposing Data for External Consumption

Learn to extend the WordPress REST API by registering custom endpoints. We'll show you how to securely serve your Knowledge Base data as structured JSON.

Read more
WordPressWordPressJune 25, 20263 min read

Capability Checks: Securing WordPress Plugins with Authorization

Master WordPress security by implementing capability checks. Learn to use current_user_can to restrict admin features and enforce proper access control.

Read more
4

Defining the Plugin Core Class

4 min
  • 5

    Understanding WordPress Hooks

    4 min
  • 6

    Implementing Custom Action Hooks

    4 min
  • 7

    Managing Hook Priorities

    3 min
  • 8

    Creating Admin Menus

    3 min
  • 9

    The Controller Layer for Admin Pages

    3 min
  • 10

    Registering Custom Post Types

    3 min
  • 11

    Configuring CPT Arguments

    3 min
  • 12

    Introduction to Taxonomies

    3 min
  • 13

    Designing Meta-Boxes

    3 min
  • 14

    Sanitizing User Input

    4 min
  • 15

    Saving Meta Data

    3 min
  • 16

    Database Basics with wpdb

    3 min
  • 17

    Secure CRUD Operations

    3 min
  • 18

    Querying with WP_Query

    3 min
  • 19

    Optimizing Queries

    3 min
  • 20

    The Model Layer for Data

    3 min
  • 21

    Enqueuing Scripts and Styles

    3 min
  • 22

    Plugin Template Hierarchy

    3 min
  • 23

    Creating Frontend Templates

    3 min
  • 24

    Building Shortcodes

    3 min
  • 25

    Advanced Shortcode Logic

    3 min
  • 26

    Introduction to Gutenberg Blocks

    3 min
  • 27

    The Settings API

    3 min
  • 28

    Validating Settings

    3 min
  • 29

    Implementing Nonces

    3 min
  • 30

    Capability Checks

    3 min
  • 31

    Handling Plugin Updates

    3 min
  • 32

    Internationalization (i18n)

    3 min
  • 33

    Debugging WordPress Plugins

    4 min
  • 34

    Unit Testing Foundations

    3 min
  • 35

    Handling AJAX Requests

    3 min
  • 36

    REST API Integration

    3 min
  • 37

    Advanced Database Queries

    3 min
  • 38

    Caching Strategies

    3 min
  • 39

    Plugin Security Best Practices

    Coming soon
  • 40

    Composer for Dependencies

    Coming soon
  • 41

    Theme Integration Hooks

    Coming soon
  • 42

    Managing Assets with Gulp/Webpack

    Coming soon
  • 43

    Documentation Standards

    Coming soon
  • 44

    Plugin Deployment Strategy

    Coming soon
  • 45

    Advanced MVC: Dependency Injection

    Coming soon
  • 46

    Handling Large Datasets

    Coming soon
  • 47

    Error Handling and Logging

    Coming soon
  • View full course