File structure
It should be either one PHP file inside the plugins directory or a folder that contains PHP files.
Example:
// A single-file plugin:
wp-content/plugins/my-first-plugin.php
// A plugin in its own directory:
wp-content/plugins/example-plugin/example-plugin.php
wp-content/plugins/example-plugin/my-logo.png
The file name itself doesn’t really matter — what matters is that one of the files has the header comment.
Comment header
Minimal header:
/**
* Plugin Name: YOUR PLUGIN NAME
*/
Recommended header:
/**
* Plugin Name: My Basics Plugin
* Plugin URI: https://example.com/plugins/the-basics/
* Description: Handle the basics with this plugin.
* Version: 1.10.3
* Requires at least: 5.2
* Requires PHP: 7.2
* Author: John Smith
* Author URI: https://author.example.com/
* License: GPL v2 or later
* License URI: https://www.gnu.org/licenses/gpl-2.0.html
* Update URI: https://example.com/my-plugin/
* Text Domain: my-basics-plugin
* Domain Path: /languages
*/
PHPDoc DocBlock:
/**
* Plugin Name
*
* @package PluginPackage
* @author Your Name
* @copyright 2019 Your Name or Company Name
* @license GPL-2.0-or-later
*
* @wordpress-plugin
* Plugin Name: Plugin Name
* Plugin URI: https://example.com/plugin-name
* Description: Description of the plugin.
* Version: 1.0.0
* Requires at least: 5.2
* Requires PHP: 7.2
* Author: Your Name
* Author URI: https://example.com
* Text Domain: plugin-slug
* License: GPL v2 or later
* License URI: http://www.gnu.org/licenses/gpl-2.0.txt
* Update URI: https://example.com/my-plugin/
*/
Here’s a list of all the header fields: open_in_new header fields .
Only one file in the plugin’s folder should have the header comment — if the plugin has multiple PHP files, only one of those files should have the header comment.
Avoiding function name collisions
The first solution is to prefix every function in your plugin with a unique string:
function my_plugin_publish_post_action() {
// ...
}
add_action('publish_post', 'my_plugin_publish_post_action');
The second solution is to enclose your plugin functions in a class and call the class methods statically.
class MyPlugin {
public static function publish_post_action() {
// ...
}
}
add_action('publish_post', ['MyPlugin', 'publish_post_action']);
Security
if ( ! defined( 'ABSPATH' ) ) {
exit; // Exit if accessed directly
}
Activation
If you are wondering how a plugin is activated, the explanation is simple: plugin code is executed after the “Activate” button is clicked, then the activation hook is executed.
Plugin API
|
Filter functions:
|
Action functions:
|
Activation / deactivation / uninstall functions:
| register_activation_hook() |
| register_deactivation_hook() |
| register_uninstall_hook() |
Plugin structure
The root level of your plugin directory should contain your
plugin-name.phpfile and, optionally, youruninstall.phpfile. All other files should be organized into sub folders whenever possible.
A sample folder structure for reference:
/plugin-name
plugin-name.php
uninstall.php
/languages
/includes
/admin
/js
/css
/images
/public
/js
/css
/images
The admin and public split isn’t just cosmetic — it lets you load only the half that the current
request needs:
if ( is_admin() ) {
// we are in admin mode
require_once( dirname( __FILE__ ) . '/admin/plugin-name-admin.php' );
}
I guess a good starting point is to use the open_in_new WordPress Plugin Boilerplate .
There’s a generator for this: open_in_new https://wppb.me
Packing a plugin into a zip file
zip -r pugin-name-v1.0.0.zip plugin-folder-name
Andrew Dorokhov