Part 2: Basic Anatomy of a WordPress Plugin

Basic Anatomy of a WordPress Plugin

Basic Plugin File Structure

When developing a WordPress plugin, especially one that may grow in complexity, it’s crucial to follow a structured, scalable, and organized file and folder structure. Adopting an object-oriented programming (OOP) approach and utilizing classes can significantly enhance the scalability and maintainability of your plugin. Here’s a basic suggested file structure that considers growth and best practices. This is pretty much a suggested WordPress minimum. I’ll go into a deeper more scalable structure in a later chapter:

  • my-plugin.php: The main plugin file that contains the plugin header information and initializes the necessary files to run the plugin.

  • includes/: This directory contains the core functionality classes and functions of your plugin.

  • admin/: This directory contains all the files related to the WordPress admin area, such as CSS, JavaScript, and partial HTML files.

  • public/: This directory contains all the files that will affect the public-facing part of the website.

  • languages/: This directory is used to store language files for internationalization. If you’re into that sort of thing. 
├── includes/
│   ├── class-my-plugin.php
│   ├── class-my-plugin-admin.php
│   └── class-my-plugin-public.php
├── admin/
│   ├── css/
│   ├── js/
│   └── pages/
├── public/
│   ├── css/
│   ├── js/
│   └── pages/
├── languages/
├── my-plugin.php
└── README.txt


Creating and Activating a Plugin Built for Growth

1. Plugin Header and Main File

In your my-plugin.php, define the plugin header and include the necessary files. Also, define the activation and deactivation hooks.

There are several reasons why it’s good practice to keep the main my-plugin.php file separate from other included files:

Organizational Clarity: Keeping the main file separate allows developers to quickly understand the primary entry point of the plugin. They can easily identify what the plugin does by looking at the main file and then drill down into the specifics by exploring the included files.

Ease of Maintenance: If there’s a specific functionality that needs updating, you can directly access the relevant include file without having to wade through unrelated code.

Modularity: With separate include files, you can easily reuse pieces of code across multiple plugins or projects. 

Performance: While PHP is generally fast in including files, segregating functionalities allows you to conditionally include files only when they’re needed.

 * Plugin Name: My Plugin
 * Description: A scalable WordPress plugin.
 * Version: 1.0
 * Author: Your Name

// If this file is called directly, abort.
if ( ! defined( 'WPINC' ) ) {

// Include classes.
require_once plugin_dir_path( __FILE__ ) . 'includes/class-my-plugin.php';

// Activation and deactivation hooks.
register_activation_hook( __FILE__, array( 'My_Plugin', 'activate' ) );
register_deactivation_hook( __FILE__, array( 'My_Plugin', 'deactivate' ) );

// Initialize the plugin.


2. Utilizing Classes and OOP

In the includes/ directory, utilize classes to encapsulate functionalities and enable scalability.

class-my-plugin.php: The main class that initializes the plugin, loads dependencies, and defines hooks. This is called be the originating file in the root folder of the plugin my-plugin.php shown above.

class-my-plugin-admin.php and class-my-plugin-public.php: Define classes that handle functionalities for the admin and public-facing parts of the website, respectively.

About using Classes and Data Encapsulation throughout your plugin. 

Data encapsulation, at its core, is a design principle that promotes organizing and bundling data with the methods that operate on it. While encapsulation can contribute to better code organization and maintainability, it doesn’t inherently guarantee security, but then again nothing does. Since WordPress plugins share space with other plugins, the weakest security is the losing factor.

So don’t get overly confident in using classes, while encapsulation can contribute to better software design and can limit unintended interactions with an object’s data, it doesn’t inherently make your code secure. Proper validation, sanitization, and other security measures are essential regardless of encapsulation.

					class My_Plugin {

    private static $instance = null;

    public static function get_instance() {
        if ( null === self::$instance ) {
            self::$instance = new self();
        return self::$instance;

    private function __construct() {

    private function load_dependencies() {
        require_once plugin_dir_path( dirname( __FILE__ ) ) . 'includes/class-my-plugin-admin.php';
        require_once plugin_dir_path( dirname( __FILE__ ) ) . 'includes/class-my-plugin-public.php';

    private function define_hooks() {
        // Define admin and public hooks here.

    public static function activate() {
        // Code to run on plugin activation.

    public static function deactivate() {
        // Code to run on plugin deactivation.


3. Admin and Public Functionalities

In the admin/ and public/ directories, store assets like CSS and JavaScript files that are specific to the admin and public areas, respectively.  While the classes for the admin and public are stored here in includes/ in this basic explanation, you can expect to see them moved to the admin/ and public/ directories in the more advanced example coming in a future step. 

Utilize pages area to store and call reusable HTML components and snippets. Pretty much anything that is visual that occurs within the pages whether those be admin pages or public pages respectively.


– Create a basic plugin using the above structure.
– Activate the plugin and ensure no errors are encountered.
– Add a simple admin page using the class structure.

Additional Resources