WordPress Plugin Development Tutorial Manual - Plugin Basics Tutorials
WordPress Plugin Development Basics
Getting Started with Plugin Development
Simply put, a WordPress plugin is a PHP file with a WordPress plugin header comment, and we highly recommend creating a directory for the plugin in order to keep the plugin files neatly organized and easy to maintain.
To create a new WordPress plugin, follow these steps.
- Switch to the wp-content/plugins directory on your WordPress site.
- Create a new directory and name it with the name of the plugin, e.g. (plugin-name)
- Switch to your newly created directory
- Create a PHP file (the plugin name should ideally be the same as the directory name. Of course, other names are also possible)
The following is the procedure for completing the above steps from the command line on a Unix-like system
wordpress$ cd wp-content/plugins
plugins$ mkdir plugin-name
plugins$ cd plugin-name
plugin-name$ vi plugin-name.php
In the example above, vi is the name of the text editor, and you can use any editor you like.
After opening the PHP file created above, we can start developing the WordPress plugin, first, we need to add aPlugin header annotationsThis is a specially formatted PHP block comment that contains metadata about the plugin, such as the plugin name and author. The header comment needs to contain at least the name of the plugin. Only one file in the plugin directory can contain the plugin header comment; if your plugin has more than one PHP file, none of the other files should contain this header comment.
<?php
/*
Plugin Name: YOUR PLUGIN NAME
*/
Save the above file and then open the WordPress plugin list screen, we can see the plugin we created in the WordPress installed plugins.
Hooks: Action and Filter
WordPress hooks allow us to intervene in the WordPress code execution flow at a specific time and change the behavior of WordPress without editing any core files,.
There are two types of hooks in WordPress, Actions and Filters. Actions allow us to add or modify WordPress functionality, while Filters allow us to modify content submitted by users or displayed to users.
In addition to being used in WordPress plugins, hooks are also widely used in many features of WordPress core, some hooks are just placeholders buried in WordPress for us to use when we develop, which is what makes WordPress so flexible.
Basic hooks for plugin development
The 3 basic hooks required to create a plugin are register_activation_hook()(math.) genusregister_deactivation_hook() respond in singing register_uninstall_hook()The
- register_activation_hook Runs when we activate our plugin, we can use this hook to mount a function to set up our plugin, for example to add some default settings in the datasheet.
- register_deactivation_hook runs when we disable the plugin, and we can mount a function that cleans up the plugin data to clean up some temporary data.
- register_uninstall_hook Runs when we uninstall a plugin, and we can mount a function that cleans up all the data for the plugin to clean up the database of plugin data that is no longer needed.
Adding custom hooks
We can use the do_action() function to add our own hooks. With our own custom hooks, other developers can adapt our plugin to their needs by extending or modifying it.
Removing functions mounted to hooks
We can use the remove_action() to remove a function mounted on a hook. For example, if a plugin is an extension of another plugin, we can use remove_action to remove the callback function that the extension plugin has added to this hook, and then add our own callback function, in which case we need to pay special attention to the priority of the plugin's action, because the remove_action() It is necessary to add the initial add_action() Run it afterward.
We should be very careful when removing actions from hooks or changing the priority of an action, as it is difficult to see how these changes will affect other actions mounted on the same hook. It is highly recommended to do some more testing when using this action.
We can find out more about this in this manual'shookschapter to learn more about creating hooks and interacting with them.
WordPress API
Did you know that WordPress offers a lot of Application Programming Interfaces (APIs)These APIs can greatly reduce the amount of code we need to write when developing plugins. These APIs can greatly reduce the amount of code we need to write when developing plugins. We don't want to reinvent the wheel, especially after the existing wheel has been developed and tested a lot and is stable enough.
The most common of these are Options API, it helps us to save the data to the database very easily. If you need to use the plugin in cURLThen you may be interested in HTTP API Interested.
Since we're discussing how to develop WordPress plugins, learning about Plug-in API is necessary, and many of these features can help us develop plugins more quickly.
How to load WordPress plugins?
When we open the list of installed plugins in the WordPress backend, WordPress searches the wp-content/plugins directory (and its subdirectories, which is the plugin's own directory) for the PHP file with the WordPress plugin header file. If our plugin is just a PHP file such as Hello If our plugin is just a PHP file, such as Hello Dolly, the file can be placed directly in the root of the wp-content/plugins directory. However, it is more common that the plugin will have its own directory, and the plugin file will be stored in its own directory, with the name of the directory as the name of the plugin file.
Share your plugin
Sometimes we develop plugins only for our own sites, but more people like to share their plugins to the WordPress community. Before sharing a plugin, we need toSelect a licenseThe license lets users know how they are allowed to use our code. For compatibility with WordPress core licenses, it is recommended to choose a license that applies to the GNU General Public License (GPLv2 +).
Header file requirements
As described in Getting Started, the plugin header file tells WordPress what kind of plugin it is. The header file needs to contain at least the plugin name, and optionally the following sections (which should usually be included):
- Plugin Name:(indispensable) The name of your plugin will show up in the list of plugins in the WordPress backend.
- Plugin URI:The plugin homepage, should be a unique URL, preferably on your own site. For your plugin, it must be unique and not use the URL on WordPress.org.
- Description:A short description of the plugin, which is displayed in the WordPress plugin management interface, should not exceed 140 characters.
- Version:The current version number of the plug-in, e.g. 1.0 or 1.0.3.
- Author:Plugin author name, if the plugin has more than one author, the authors can be separated by commas.
- Author URI:Personal data on the author's website or on other websites, such as WordPress.org.
- License:Plug-in license abbreviation (slug) (e.g. GPL2). More information about the license can be found in theWordPress.org GuideFind.
- License URI: LicenseThe link to the full text (e.g., https://www.gnu.org/licenses/gpl-2.0.html) of the
- Text field:plug-in (computing) Gettext Text field. More information can be found in theHow to internationalize your pluginpage is found in the Text Fields section of the page.
- Domain Path:The domain path tells WordPress where to find the translation. More information can be found in theHow to internationalize your plugin page is found in the Domain Paths section.
The correct format for plugin header comments can be seen in the following example:
<?php
/*
Plugin Name: WordPress.org Plugin
Plugin URI: https://developer.wordpress.org/plugins/the-basics/
Description: Basic WordPress Plugin Header Comment
Version: 20160911
Author: WordPress.org
Author URI: https://developer.wordpress.org/
License: GPL2
License URI: https://www.gnu.org/licenses/gpl-2.0.html
Text Domain: wporg
Domain Path: /languages
*/
Software license included
Most WordPress plugins are released under the GPL license, which is also used by the WordPress kernel. Of course, we can choose other licenses as well, and regardless of which license is used, it is best to specify the plugin license when releasing the plugin.
In the Header File Requirements section, we briefly explained how to specify the plugin license in the plugin header file comments, another common and encouraged practice is to include a license block comment at the top of the plugin's main file, as exemplified below:
/*
{Plugin Name} is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 2 of the License, or
any later version.
{Plugin Name} is distributed in the hope that it will be useful, but WITHOUT ANY WARNING.
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
You should have received a copy of the GNU General Public License along with {Plugin Name}. If not, see {URI to Plugin License}.
*/
When used with plugin header comments, it should look like the following.
<?php
/*
Plugin Name: WordPress.org Plugin
Plugin URI: https://developer.wordpress.org/plugins/the-basics/
Description: Basic WordPress Plugin Header Comment
Version: 20160911
Author: WordPress.org
Author URI: https://developer.wordpress.org/
Text Domain: wporg
Domain Path: /languages
License: GPL2
{Plugin Name} is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 2 of the License, or
any later version.
{Plugin Name} is distributed in the hope that it will be useful, but WITHOUT ANY WARNING.
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
You should have received a copy of the GNU General Public License along with {Plugin Name}. If not, see {License URI}.
*/
Activate/deactivate hooks
The activation and deactivation hooks allow us to perform a number of actions when activating or deactivating the plugin.
On activation, we can mount a function to add URL rewrite rules, or add plugin settings to the database.
When disabled, we can mount a function to remove temporary data such as caches and temporary files and directories.
activation
If you need to add a function to the activation hook, use the register_activation_hook() function.
register_activation_hook( __FILE__, 'pluginprefix_function_to_run' );
prohibit the use of sth.
If you need to add a function to the disable hook, use the register_deactivation_hook() function.
register_deactivation_hook( __FILE__, 'pluginprefix_function_to_run' );
The first parameter in each function points to the main file of the plugin (i.e. the file containing the plugin header comments). These two functions are usually triggered in the main file of the plugin, but of course we can put them in other files, in which case we have to update the first parameter to the correct location.
typical example
One of the most common uses of activation hooks is to flush the WordPress fixed link cache when a plugin registers a custom post type, which allows us to avoid encountering 404 errors. Example is shown below:
function pluginprefix_setup_post_type() {
// Register the book's custom post type
register_post_type( 'book', ['public' => 'true'] );
}
add_action( 'init', 'pluginprefix_setup_post_type' );
function pluginprefix_install() {
// Trigger the register custom post type action
pluginprefix_setup_post_type();
// Flush the fixed link cache after registering a post type.
flush_rewrite_rules(); }
}
register_activation_hook( __FILE__, 'pluginprefix_install' );
If you don't know how to register a custom post type, don't worry, we'll cover that later, the example above is simple but common.
The above example is for activating the plugin, let's see how to undo the above action when the plugin is disabled.
inprefix_deactivation() {
// Unregister the post type
unregister_post_type( 'book' ); // Refresh the fixed link cache.
// Flush the fixed link cache
flush_rewrite_rules();
}
register_deactivation_hook( __FILE__, 'pluginprefix_deactivation' );
For more information on plugin activation and disabling hooks, please refer to the following links:
- register_activation_hook() WordPress Functions Reference.
- register_deactivation_hook() WordPress Functions Reference.
Uninstallation method
If our plugin adds some settings to the database or generates some cache files when the user uses the plugin, when the user uninstalls the plugin, these settings and files are likely to be useless. We need to delete this data when the user uninstalls the plugin. The following table illustrates the difference between deactivation and uninstallation hooks.
manipulate | Disable Hooks | Unloading Hooks |
---|---|---|
Refresh the cache generated by the plugin | be | clogged |
Flush the Url Rewrite Rules Cache | be | clogged |
Remove the data added by the plugin from the {$wpdb->prefix}_options datasheet | clogged | be |
Removing tables from wpdb | clogged | be |
Method 1: register_uninstall_hook
Mount the uninstall function to the register_uninstall_hook() hook.
register_uninstall_hook(__FILE__, 'pluginprefix_function_to_run');
Method 2: uninstall.php
To use this method, we need to create a file called uninstall.php in the root directory of the plugin, and the functions in this file will be run automatically when the user uninstalls the plugin.
Example: /plugin-name/uninstall.php
best practice
Here are some best practices for WordPress plugin development that can help us organize our code more logically when developing plugins.
Avoiding naming conflicts
Naming conflicts occur when our plugin and other themes or plugins use the same function or class name. Fortunately, we can avoid naming conflicts with the following method.
Why Product Naming Conflicts
By default, all variables, functions, and classes are all in theglobal namespacedefined in a plugin or theme, which means that one plugin or theme can override another plugin's variables, functions, and classes (variables defined in a function or class will not be overridden).
Prefix all definitions
All variables, functions, and classes should have a unique prefix. The prefix helps us avoid using the same variable, function, and class names as other plugins, and also prevents these definitions from being overwritten by other plugins or themes.
Check all definitions
PHP provides a number of functions to verify the existence of variables, functions, classes, and constants, and if these definitions exist, these functions will return true
- variant: isset() (include arrays, objects, etc.)
- function (math.): function_exists()
- resemble: class_exists()
- constant: defined()
typical example
<?php
//Create a function called wporg_init if it doesn't already exist
if ( !function_exists( 'wporg_init' ) ) {
function wporg_init() {
register_setting( 'wporg_settings', 'wporg_option_foo' ); }
}
}
//Create a function called wporg_get_foo if it doesn't already exist
if ( !function_exists( 'wporg_get_foo' ) ) {
function wporg_get_foo() {
return get_option( 'wporg_option_foo' ); }
}
}
OOP object-oriented programming
A simpler way to resolve namespace conflicts is to use classes to organize the plugin's code. When using this method, we still need to check if the class name is already in use by another plugin or theme, as opposed to a non-OOP transformation, where we only need to check the class name.
typical example
<?php
if ( !class_exists( 'WPOrg_Plugin' ) ) {
class WPOrg_Plugin
{
public static function init() {
register_setting( 'wporg_settings', 'wporg_option_foo' ); }
}
public static function get_foo() {
return get_option( 'wporg_option_foo' ); }
}
}
WPOrg_Plugin::init();
WPOrg_Plugin::get_foo();
}
Organize plug-in files
The plugin root directory should contain a plugin-name.php file named plugin-name, or, if you need to perform some action when uninstalling, the uninstall.php file, other files are organized into subdirectories of the plugin if possible, and subdirectory names should conform to semanticization rules as much as possible.
directory structure
A clear directory structure should keep files that are similar in type or function in the same directory, below is an example directory structure.
/ plugin-name
plugin-name.php
uninstall.php
/ languages
/ includes
/ admin
/ js
/ css
/ images
/ public
/ js
/ css
/ images
plug-in architecture
The architecture or code organization style chosen for the plugin depends on the size of the plugin.
For small, single-purpose plugins with limited interaction with the WordPress kernel, themes, or other plugins, using a single file is fine. There is no benefit to using a complex structure like classes unless we know that the plugin will have many extensions in the future.
For large plugins with a lot of code, we should refer to the above directory structure, and put the styles, JavaScript scripts independently, and the different functions or classes that realize the plugin's functionality also try to be independent and put in a separate subdirectory, which will help to keep the plugin's code clear and maintain it in the long run.
Load on Demand
It is necessary to separate the administrative code of the plugin from the public code, and we can do this using the WordPress conditional function is_admin, for example:
<?php
if ( is_admin() ) {
// we are in admin mode
require_once( dirname( __FILE__ ) . '/admin/plugin-name-admin.php' );
}
architectural model
Although there are many structural patterns, they can be broadly categorized into 3 types
- Single file with many functions
- Single-core plugin file that contains a class and then instantiates that class
- There is a main plugin file that contains one or more class files
Starter Sample Plugin
If writing a plugin directly from scratch would do a lot of unnecessary repetitive work, we can use sample plugins to develop each new plugin. One of the advantages of using sample files is consistency across our plugins. It's also easier for users of the plugin to contribute code to the plugin if they are already familiar with the sample plugin. Here are a few common WordPress sample plugin projects.
- WordPress Plugin Boilerplate: The foundation of WordPress plugin development, designed to provide clear, consistent guidance for building plugins.
- WordPress Plugin Bootstrap: Sample plugins using Grunt, Compass, Git and Svn.
- WP Skeleton Plugin: Focus on unit testing and sample plugins using Composer
- Search for starter plugins on GIthub
Of course, we can also define our own sample plugins according to our needs and style.