When we want to extend functionality in WordPress project, we cannot do changes in core files because, WordPress updates frequently (currently at verion 5) and all changes will be overwritten back to default files of new version. Hence, the need for plugins for adding extra functionality. There are steps to develop a plugin. WordPress also provides its own guide at  https://codex.wordpress.org/Writing_a_Plugin in order to create a plugin WordPress, however, that guide can be intimidating for new users. So, here we provide a tutorial to develop a WordPress plugin. These are our experiences and process we employ at The Right Software to develop a WordPress plugin. We’ll go through some topics first and towards the end, develop a sample plugin (with code).

File structure of WordPress plugin


File structure of WordPress plugin for approval

If you want to submit the plugin you develop to WordPress.org directory, then follow the structure below. There will be one readme file and 2 folders, One is assets folder that will have all the plugin screenshots and css, js files, Second is the trunk folder that will have plugin PHP files. The .git folder is for TRS internal use and you can discard it. WordPress.org uses SVN version control instead of Git.


Now, lets start creating files for the plugin.

No direct access to plugin functionality

WordPress plugin need to block direct access to php files by checking ABSPATH variable is defined. For this you need to add following code at the top of plugin php files. So make sure that if you have a library or multiple plugin files then the line below is added to all the files.

defined( 'ABSPATH' ) or die( 'Nope, not accessing this' );

Plugin declarations

Plugin declaration are text comments that WordPress will use to define your entry in the plugin list. It must have plugin name at least. You can also add plugin description, uri, version, author, license etc. All that will be in PHP comments quotes. Plugin declaration block should be added to main plugin PHP file.

Plugin Name: WordPress Test Plugin
Plugin URI:  https://therightsw.com
Description: Test description
Version:     1.0.0
Author:      therightsw
Author URI:  http https://therightsw.com
License:     GPL2
License URI: https://www.gnu.org/licenses/gpl-2.0.html


WordPress hooks

Hooks are like tentacles that your WordPress plugin sinks into the WordPress core and extends or overrides the functionality. Three types of hooks are used in WordPress to override existing WordPress and add new functionality.

Filter hook

WordPress filters hooks can be added or remove and also new can be created.To learn more about what filter hook is, see Plugin API.

add_filter('the_content', 'custom_meta_to_content'); //gets our meta data and dispayed it before the content

Action hook

WordPress action hooks can add or remove and also new can be created. To learn more about what action hook is, see Plugin API..

add_action('admin_enqueue_scripts', 'enqueue_admin_scripts_and_styles'); //admin scripts and styles


Mostly defined and used for adding extra functionality.

add_shortcode('wp_custom_text', 'func_wp_custom_text'); //will be used to add custom text by adding this shortcode where you want.

The register_activation_hook and register_deactivation_hook functions are used to hook into functions when the plugin is activated or deactivated.

WordPress plugin security

WordPress security standards become high so they do not accept plugin that not has proper secure code. following is the standard used to secure plugin code.

Generic function

All plugins must have unique function names, defines, and class names. This prevents your plugin from conflicting with other plugins or themes. Also good for having your plugin approved by WordPress.

For example, if your plugin is called “Easy Custom Post Types”, then you might prefix your functions with ecpt_{your function name here}. Similarly a definition of LICENSE would be better done as ECPT_LICENSE. You can use namespaces instead, however make sure that those also are unique. A namespace or class of ‘MyPlugin’ is NOT actually all that unique.

This extends to anything in a define. For example, if you were to use this, it would be a bad idea:


define( 'PLUGIN_PATH', plugins_url( __FILE__ ) );

That define is a global, so PLUGIN_PATH could conflict with a number of other things.

 Don’t try to use two letter slugs anymore. As of 2016, all the good ones are taken. Instead consider easy_cpts_ (from the first example).

Similarly, don’t use __ (double underscores), wp_ , or _ (single underscore) as a prefix. Those are reserved for WordPress itself. You can use them inside your classes, but not as stand-alone function.

Use more unique function and class names for your plugin.

Use Nonces and check permissions

Add a nonce to your POST calls to prevent unauthorized access.

Sanitize, escape, and validate your POST calls

When you include POST/GET/REQUEST calls in your plugin, it’s important to sanitize, validate, and escape them. The goal here is to prevent a user from accidentally sending trash data through the system, as well as protecting them from potential security issues.

SANITIZE: All instances where generated content is inserted into the database, or into a file, or being otherwise processed by WordPress, the data MUST be properly sanitized for security. By sanitizing your POST data when used to make action calls or URL redirects, you will lessen the possibility of XSS vulnerabilities. You should never have a raw data inserted into the database, even by a update function, and even with a prepare() call.

If you had text input field like

<input name="your-name" type="text" />

You could sanitize it using sanitize_text_field() function.

$name = sanitize_text_field( $_POST['your-name'] );
update_post_meta( $post->ID, 'your-name', $name );

Other functions used for sanitizing the data are.

VALIDATE: In addition to sanitization, you should validate all your calls. If a $_POST call should only be a number, ensure it’s an int() before you pass it through anything. Even if you’re sanitizing or using WordPress functions to ensure things are safe, we ask you please validate for sanity’s sake. Any time you are adding data to the database, it should be the right data.

For example if you want zipcode in integers then intval() function will be used to validate the input value.

$zipcode = intval( $_POST['zipcode'] );

ESCAPE: When you’re outputting data, make sure to escape it properly, so it can’t hijack admin screens. There are many esc_*() functions you can use to make sure you don’t show people the wrong data.

In all cases, using stripslashes or strip_tags is not enough. You need to use the most appropriate method associated with the type of content you’re processing. Check that a URL is a URL and don’t just be lazy and use sanitize_text please. The ultimate goal is that you should ensure that invalid and unsafe data is NEVER processed or displayed. Clean everything, check everything, escape everything, and never trust the users to always have input sane data.

Some commonly used helper function are as follows.

esc_html() used HTML element encloses a section of data we’re outputting.
<h2><?php echo esc_html( $title ); ?></h2>

esc_url() used for all URLs of HTML element.
<img src="<?php echo esc_url( $great_user_picture_url ); ?>" />

esc_js() is intended for inline Javascript.
<a href="#" onclick="<?php echo esc_js( $custom_js ); ?>">Click me</a>

esc_attr() can be used on the data into an HTML element’s attribute.
<div id="<?php echo esc_attr( $element_id ); ?>"></div>

esc_textarea() encodes in textarea element.
<textarea><?php echo esc_textarea( $text ); ?></textarea>


Let’s actually develop a WordPress plugin

Now, lets develop your first WordPress plugin. As an example, I am going to create sample plugin which will be used to add custom text (it could be simple paragraph or heading etc.) anywhere in website. You can download this small sample plugin using the link at the bottom of the article.

1) Create plugin directory in /wp-content/plugins and name it to WordPress-Custom-Text-Shortcode.
2) Create trs-custom-text.php file and add plugin declaration.[/vc_column_text][vc_column_text 0=””]

Plugin Name: WordPress Custom Text Shortcode
Plugin URI:  https://therightsw.com
Description: You can add your desired text anywhere in website by using WordPress Custom Text Shortcode.
Version:     1.0.0
Author:      therightsw
Author URI:  http https://therightsw.com
License:     GPL2
License URI: https://www.gnu.org/licenses/gpl-2.0.html


3) Activation/Deactivation:

function wp_custom_text_activation() {
register_activation_hook(__FILE__, 'wp_custom_text_activation');
function wp_custom_text_deactivation() {
register_deactivation_hook(__FILE__, 'wp_custom_text_deactivation');

4) Create custom menu hook to diplsay plugin menu in wp-admin:

// create custom plugin settings menu
add_action('admin_menu', 'wp_custom_text_create_menu');

function wp_custom_text_create_menu() {

	//create new top-level menu
	add_menu_page('Custom Text Shortcode Plugin Settings', 'Custom Text Shortcode', 'administrator', __FILE__, 'wp_custom_text_settings_page' );

	//call register settings function
	add_action( 'admin_init', 'register_wp_custom_text_settings' );

5) Register plugin setting:

function register_wp_custom_text_settings() {
	//register our settings
	register_setting( 'trs-custom-text-settings-group', 'wp_custom_text' );

6) Setting display page code:

function wp_custom_text_settings_page() {
<div class="wrap">

<h1>Your Custom Text></h1>

<form method="post" action="options.php">
   <table class="form-table">
      <tr valign="top">
        <th scope="row" </td>



7) Create shortcode used to display custom text:

add_shortcode("wp_custom_text_shortcode", "wp_custom_text_shortcode_function");

function wp_custom_text_shortcode_function() {
return get_option( 'wp_custom_text' );

Download above sample plugin from given link.



If you follow this detailed tutorial, you can learn to Develop a WordPress plugin. If you get stuck, send us an email below, we’ll be right with you. We also provide plugin development services for WordPress and all other CMS and eCommerce software.