Simplifying WordPress Plugin Development Using Object-Oriented Programming: Part 1 — Bootstrapping The Plugin

Kofi Mokome, MTech
7 min readAug 14, 2023

--

Introduction

As a WordPress plugin developer, I have noticed that many people find it difficult to understand certain aspects of WordPress plugin development. This led me to start working on a project to simplify some of the complex WordPress plugin tasks using object-oriented programming. It took me a long time to fully understand how the WordPress settings API works. That is why in my first article, Demystifying WordPress Settings API using OOP, I created a tool that can interact with the WordPress Settings API. In this article, I will show you how you can use the other tools I have created to simplify your WordPress plugin development.

We shall use the following tools in this series:

  • KMRoute: A tool that enables you to create custom routes in WordPress.
  • KMMigration: Creating and managing custom database tables can become a difficult task. This tool allows you to easily create database migrations which will be automatically converted to database tables. It also helps you update an existing table without writing a single SQL command. Can you imagine 😳?
  • KMModel: This tool makes querying (create, read, update, delete) data in your tables in the WordPress database as easy as ABC. You will be amazed by how much time you can save using this tool.
  • KMValidator: This tool helps you validate your REST API requests. Gone are the days when you write a dozen if-else statements.
  • KMMenuPage and KMSubMenuPage: These tools help you create custom WordPress admin menu items and sub-menu items.

You will see a lot of similarities between these tools and Laravel. I want to thank Taylor Ortwell. Laravel has been my main source of inspiration while building these tools.

Note: The tools used in the article are still under development. A lot may change in the future.

What You Will Learn: Overview

In this article, we will build a question-answer plugin that allows a registered user to ask and answer questions. You can download the codes from the GitHub Repository.

This article assumes you already know how to create a WordPress plugin. I would try my best to simplify the steps as much as I can.

Project Setup

If you have not yet installed WordPress on your PC, you can download and install the latest version from WordPress.org.

In the wp-content/plugins folder, we will create a new folder called wp-questions. Next, we will create a blank PHP file, wp-questions.php in the wp-questions folder. Your plugin folder should look like this:

wp-questions plugin folder

Download The Libraries

Before we write any code, let us download the tools from the WordPress Tools GitHub repository. Please leave a star ⭐️ on the repository 🤩.

Next, create a lib folder in our plugin folder. This folder will contain all the libraries we will need.

wp-questions plugin with the lib folder

Now, let us extract the contents of the zip file into the lib folder

wp-questions plugin with the lib folder

Copy the .env.example file in the wordpress_tools folder to the plugin’s root directory. Rename the file to .env

Plugin folder with the .env file

Plugin Activation Script

Great 😊 . Now that we have our libraries downloaded, let us set up the plugin activation script. We will use the wp_questions namespace in all our PHP files

Namespace allows for better organization by grouping classes that work together to perform a task

In the wp-questions.php file, we add the following code

<?php

namespace wp_questions;

use WordPressTools;

defined( 'ABSPATH' ) or die( 'Giving To Cesar What Belongs To Caesar' );

/**
* @link www.example.org
* @since 1.0.0
* @package wp_questions
*
* @wordpress-plugin
* Plugin Name: WP Questions
* Plugin URI: https://some-url.com
* Description: <<Add Description>>.
* Version: 1.0.0
* Author: Kofi Mokome
* Author URI: https://github.com/kofimokome
* License: GPL-2.0+
* License URI: http://www.gnu.org/licenses/gpl-2.0.txt
* Text Domain: wp-questions
* Domain Path: /languages
*/

/**
* Shows an error message on the admin dashboard
* @since 1.0.0
* @author kofimokome
*/

const WPQ_TEXT_DOMAIN = 'wp-questions';

function ErrorNotice( $message = '' ): void {
if ( trim( $message ) != '' ):
?>
<div class="error notice is-dismissible">
<p><strong>WP Questions: </strong><?php echo esc_attr( $message ) ?></p>
</div>
<?php
endif;
}

add_action( 'admin_notices', 'wp_questions\\ErrorNotice', 10, 1 );


$error = false;

// scan directories for requires.php files
foreach ( scandir( __DIR__ ) as $dir ) {
if ( strpos( $dir, '.' ) === false && is_dir( __DIR__ . '/' . $dir ) && is_file( __DIR__ . '/' . $dir . '/requires.php' ) ) {
require_once __DIR__ . '/' . $dir . '/requires.php';
}
}

$requires = apply_filters( 'kmwpq_requires_filter', [] );

foreach ( $requires as $file ) {
if ( ! $filepath = file_exists( $file ) ) {
ErrorNotice( sprintf( __( 'Error locating <b>%s</b> for inclusion', WPQ_TEXT_DOMAIN ), $file ) );
$error = true;
} else {
require_once $file;
}
}

$wordpress_tools = new WordPressTools( __FILE__ );

// scan directories for includes.php files
foreach ( scandir( __DIR__ ) as $dir ) {
if ( strpos( $dir, '.' ) === false && is_dir( __DIR__ . '/' . $dir ) && is_file( __DIR__ . '/' . $dir . '/includes.php' ) ) {
require_once __DIR__ . '/' . $dir . '/includes.php';
}
}

$includes = apply_filters( 'kmwpq_includes_filter', [] );

foreach ( $includes as $file ) {
if ( ! $filepath = file_exists( $file ) ) {
ErrorNotice( sprintf( __( 'Error locating <b>%s</b> for inclusion', WPQ_TEXT_DOMAIN ), $file ) );
$error = true;
} else {
include_once $file;
}
}


// remove options upon deactivation

register_deactivation_hook( __FILE__, 'wp_questions\\OnDeactivation' );

/**
* Set of actions to be performed on deactivation
* @since 1.0.0
* @author kofimokome
*/
function OnDeactivation(): void {
// set options to remove here
}


register_uninstall_hook( __FILE__, 'wp_questions\\OnUninstall' );

/**
* Set of actions to be performed on uninstallation
* @since 1.0.0
* @author kofimokome
*/
function OnUninstall(): void {
// some code here
}

register_activation_hook( __FILE__, 'wp_questions\\OnActivation' );

/**
* Set of actions to be performed on activation
* @since 1.0.0
* @author kofimokome
*/
function OnActivation(): void {
// some code here
}

// todo: for future use
load_plugin_textdomain( WPQ_TEXT_DOMAIN, false, basename( dirname( __FILE__ ) ) . '/languages' ); . '/languages' );

First, we create a constant, WPQ_TEXT_DOMAIN that holds our text-domain. The text domain is needed if you would like to make your plugin available in more than one language.

The ErrorNotice function displays a warning on the WordPress dashboard if a module is not found. To display the error on the admin dashboard, the function is added to the admin_notices action.

Sample output of ErrorNotice()

Next, we scan through the directories and imports the files needed for the plugin to function. We will look at it in a bit.

Next, we initialize the WordPress Tools library, passing the location to the plugin as a parameter.

Finally, we register the uninstall hook( OnUninstall ), activation hook ( OnActivation ), deactivation hook ( OnDeactivation) and the text domain.

Activating The Plugin

We can now go to the plugins page on the WordPress dashboard to activate the plugin by clicking on the Activate link.

Importing Modules

Now that our plugin is activated, let us import the first modules. To import the modules, we scan through all the sub-directories and import the files that are needed from that sub-directory. The files to import are either placed inside a requires.php file or an includes.php file. Files placed in the requires.php file are imported via the require statement while files in the includes.php are imported via the include statement. We also see the exposure of two filters:

  • kmwpg_requires_filter used to specify the files to be required and
  • kmwpg_includes_filter which is used to specify the files to be included.

We want to require all the files in the lib directory. We will create a requires.php file in the lib folder.

We add the following codes to the requires.php file to import all the files in the wordpress_tools folder.

<?php

/**
* Add libraries to be included
*/


add_filter( 'kmwpq_requires_filter', function ( $includes ) {
$plugin_path = plugin_dir_path( __FILE__ );

$files = [
$plugin_path . 'wordpress_tools/WordPressTools.php', //
];

return array_merge( $includes, $files );
} );

Configuring the CLI Script

The WordPressTools ships with a CLI script. To use the script, copy the wptools file in the wordpress_tools folder to the root of your plugin

Finally, open your terminal, navigate to the root of your plugin and type php wptools to see the list of commands

In the next article, we will look at using the KMModel and the KMMigration tools to create models and migrations.

--

--