Scaffold a WordPress Plugin

Writing a custom WordPress plugin can be a pain – there are a million ways to do it and a lot of WordPress code isn’t known for being the highest quality code. A clean approach to writing a WordPress plugin is using a method based format that holds all the major logic (or at least calls). Doing it this way makes it easy to keep your logic contained and makes the code maintainable.

Depending on what your end goal is, you don’t need to write to the database or you can take advantage of Corcel. In this sample plugin, we are going to go ahead and plan if we were writing to the database with Eloquent.


Let’s start off by creating a sample plugin that reads/writes to a custom table using Eloquent. We are using Composer to manage libraries.

Quick Look

There will be a sample.php, composer.json, the src folder which contains the Loader, and the vendor library.

The sample.php will not contain any logic, rather it will load the vendor autoload and the Loader.php.

composer.json

Our plugin file does two things – includes our vendor library and our loader, which we will get to later. For this plugin, we will need to install illuminate/database with Composer. While it’s out of scope for this, you may want to look into including PHP dotenv so you can manage your development and production database credentials.


{
"autoload": {
"psr-4": {
"Sample\\": "src/"
}
},
"minimum-stability": "dev",
"prefer-stable": true,
"require": {
"illuminate/database": "^7.14.1"
}
}

view raw

composer.json

hosted with ❤ by GitHub

sample.php

Now in our plugin file (sample.php), we are going to include the vendor autoload and our loader file. You’ll notice that we call an init, activate plugin, and deactivate plugin methods.


<?php
/**
* Plugin Name: Sample Plugin
* Description: A sample plugin
* Version: 1.0
*/
require_once __DIR__ . '/vendor/autoload.php';
$plugin = new \Sample\Loader(__DIR__, plugin_dir_url(__FILE__));
$plugin->init();
register_activation_hook(__FILE__, [\Sample\Loader::class, 'activatePlugin']);
register_deactivation_hook(__FILE__, [\Sample\Loader::class, 'deactivatePlugin']);

view raw

sample.php

hosted with ❤ by GitHub

Loader.php

All the plugin logic will live in the loader – actions, filters, activation/deactivation, etc… All the major plugin functionality (at a high level).  For instance, all our actions will live in a initActions method, filters in an initFilters method, etc..

So create a new folder, src, and then the Loader.php . I went ahead and add methods. for initEloquent, initActions, initFilters, and the for activatePlugin and deactivatePlugin. The names are descriptive of what they will do.


<?php
namespace Sample;
use \Illuminate\Database\Capsule\Manager as Capsule;
class Loader {
public function init() {
$this->initEloquent();
$this->initActions();
$this->initFilters();
}
protected function initEloquent() {
$params = [
'driver' => 'mysql',
'database' => '',
'username' => '',
'password' => '',
'host' => '',
'prefix' => 'wp_',
'charset' => 'utf8',
'collation' => 'utf8_unicode_ci',
];
$capsule = new Capsule();
$capsule->addConnection($params, 'default');
$capsule->setAsGlobal();
$capsule->bootEloquent();
}
protected function initActions() {
}
protected function initFilters() {
}
public function activatePlugin() {
}
public function deactivatePlugin() {
}
}

view raw

Loader.php

hosted with ❤ by GitHub

In the activatePlugin and deactivatePlugin methods, you can create your custom table and remove it. The init method will setup Eloquent and then our actions and filters. You could extend this to create custom post types, shortcodes, etc… by having methods for that and then calling them in the init method.

In just three files, we now have an easy to maintain plugin structure that is flexible and is able to utilize PHP libraries.