Bootstrapping a Plugin
This process is basically to register your plugin with Membership. Membership then handles the plugin's initialization upon resolution of dependencies.
Before we get any further, I'd like to point out that we have 2 main files:
- the main plugin file - is located in the root plugin folder and registers core application with the Membership
- the core application file - is located in
/classes/
directory and executes your plugin business logic.
Schematically it would look like this:
Main Plugin File -> Membership (via bootstrap) -> Core Application File
Step 1: Files & Directories
Directory Structure
Our plugins use the following directory structure:
/wp-content/plugins/ hji-my-plugin/ classes/ controllers/ models/ utils/ PluginBootstrap.php views/ App.php resources/ images/ scripts/ styles/ templates/ third-party/ autoload.php my-plugin.php readme.txt
Mostly, all plugins consistently use the same structure, except for cases when some directories simply do not apply (i.e. third-party
).
Naming Conventions
Class file names should match the names of their classes following CamelCase pattern.
Files with procedural code like public functions should be lower case (i.e. functions.php).
Scripts, stylesheets and config files should be in lower case as well.
Step 2: Main Plugin File
The main plugin file is the only php file (except autoload.php) that should be located in the plugin's root directory. The same file as illustrated above with the name my-plugin.php
. The autoload.php
is a standard file used in all our plugins.
The main file consists of standard WordPress header data and PHP code responsible for plugin activation.
Plugin Header
The plugin header is standard WP header with an addition of 2 custom parameters:
- HJI Package: hji-membership - which is always standard for Membership plugins.
- HJI Require Plugins: HJI Membership: 2.7.0
HJI Require Plugins accepts a comma-separated list of HJI plugins (i.e. HJI Users:1.0, HJI Responsive IDX:2.0). Each required plugin has to have a corresponding version number, which is treated as equal or more
.
HJI Membership is always required for plugins bootstrapped by Membership.
/* Plugin Name: HJI {Plugin Name} Description: {Comprehensive Description} Plugin URI: Version: 0.1 Author: Home Junction Author URI: http://HomeJunction.com Text Domain: {plugin_textdomain} License: GPL2 HJI Package: hji-membership HJI Require Plugins: HJI Membership:2.7.0 */ /* Copyright 2018 Home Junction, Inc. (email : help@homejunction.com) This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License, version 2, as published by the Free Software Foundation. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */
Bootstrapping Code
namespace hji\myplugin; require dirname(__FILE__) . '/autoload.php'; (new utils\PluginBootstrap(__FILE__, App::class))->run()
The code above has only 2 moving parts:
- requiring the autoloader to automatically load all our classes;
- instantiating PluginBootstrap and passing the current file path and fully qualified namespace for your core application file that will execute business logic of your plugin.
If you look into the source code of the PluginBootstrap, you'll see what run()
method does:
public function run() { $this->registerPlugin(); $this->setActivationProcedures(); $this->setDeactivationProcedures(); $this->setAdminNotices(); }
- Registers plugin with Membership
- Sets standard plugin activation procedures (you may define your own in your core application)
- Sets standard plugin deactivation procedures (you may define your own in your core application)
- Sets standard admin notices that may (or may not) show up for the user upon plugin activation/deactivation (think errors).
Step 3: Core Application File
Let's talk about your Core Application file. It's the actual main file that will lead to the business logic of your plugin. In Step 1 (Files & Directories) we referenced this file under /classes/App.php
.
In Step 2 you learned that we simply passed a reference (fully qualified namespace) of your Core Application class into the PluginBootstrap. This means that Membership expects to deal with a known interface, which in our case is hji\common\Plugin
. So, hji\myplugin\App
has to extend the hji\common\Plugin
class.
Example:
namespace hji\myplugin; use hji\common\Plugin; use hji\common\plugin\PluginAPI; class App extends Plugin { function __construct($mainFilePath, PluginAPI $pluginAPI = null) { parent::__construct('My Plugin Name', 'hji-my-plugin', $mainFilePath, $pluginAPI); } function init() { //@todo do great things! } }
The hji\common\Plugin
has an explicit constructor and we only need to pass the plugin name and slug parameters along with already pre-defined arguments ($mainFilePath
and $pluginAPI
). It also has an abstract Plugin::init()
method, which serves as an entry point into your plugin's code, and has to be defined in your child class (hji\myplugin\App
). After Membership instantiates your App class, it will inevitably call the App::init()
.