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
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" | |
} | |
} |
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']); |
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() { | |
} | |
} |
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.