Create WordPress Plugin – Tutorial with complete sample code

Didn’t find the right plugin for your purpose again? I know the problem, most of the time the plugins are just way too overpowered and bring a lot of features that I don’t need. In the case of small functions, it makes sense here to simply write them yourself in a small plugin. WordPress makes it easy for us here, providing a simple way that requires little knowledge.

Create a WordPress plugin – It’s that easy!

Create a WordPress plugin – example use case

In this tutorial I want to show you how to create a WordPress plugin that

  • Activating the plugin creates a new task for the internal cron job.
  • This task will then check once a day if
    • updates from the WordPress core,
    • plugin update,
    • theme updates,
    • or translation updates are available
  • and let you know via email.
  • When deactivating the plugin, this task is deregistered again

Step 1: Create files and directory

In the first step we now create all the directories and files that we need for a simple plugin. To do this, please navigate to the plugin folder of your WordPress installation and create a new folder.

In my case I call this folder “update-reminder”.

In this folder we put two empty files with the following names and file extensions:

  1. index.html
  2. updateReminder.php

Folder and File Names - WordPress PluginFolder and File Names – WordPress Plugin

Step 2: The Plugin Header

In order for WordPress to recognize our updateReminder.php file as a plugin, we need to add standard header comments to this file. This comment gives the plugin a name, description, version number and author information. Additional information such as the license, tags or, for example, a plugin website is also possible. If you want more information about the possibilities, you can read about it in the WordPress Codex.

Our header comment looks like this:

<?php
/*
Plugin Name: Update reminder
Description: Checks for updates and sends mail
Version: 1.0
Author: Tobias Keller
Author URI: https://tobier.de/
*/

WordPress already recognizes our file as a plugin and could be activated.

Step 3: Better safe than sorry

So that our PHP file cannot be executed from outside our WordPress instance, we check after the header comment whether the constant “ABSPATH” is set. The constant “ABSPATH” is defined in “wp-config.php” and contains the absolute file path to the WordPress installation.

With the following line we check whether ABSPATH is set, if this is not the case we end the execution with the message “Are you ok?”.

defined( 'ABSPATH' ) or die( 'Are you ok?' );

Step 4: Creating and calling a PHP class

In theory, we could now use functions and action hooks / filter hooks to extend our plugin with its future functionality. However, I am a fan of the overview, which would be lost so quickly with a slightly larger plugin.

That’s why I like working with classes. That’s exactly what we’re going to do now, by first inserting a class (UpdateReminder), initializing it and inserting a constructor.

$start_reminder = new UpdateReminder();

class UpdateReminder{
	public function __construct() {
    }
}

the constructor, __construct()is called each time the class is initialized.

Step 5: Execute actions when activating the plugin

Since our plugin should later automate its task and do it regularly, we need a cron job. WordPress offers us the possibility to integrate an event into the WordPress internal cron job. We have to do this once when activating the plugin.

How so?
If we add the event to the cron in every initialization, eventually we’ll have thousands of events and very likely break our website.

The “register_activation_hook”

With this hook, which is executed once upon activation and is therefore perfectly suited for our purpose, WordPress offers us an easy way to register our event. To do this, we write the following line of code in our constructor:

register_activation_hook( __FILE__, array( $this, 'updateReminder_activate' ) );

We give the hook exactly two required parameters:

  1. the absolute path to the main WordPress plugin file (in our case, the path to the file we are in)
  2. the functions to be called (within this class)

If the plugin is now activated, the “updateReminder_activate” function will be called once, in which we will register a new cron event.

Create a new WordPress cron event

In our plugin activation hook we have just defined that a function “updateReminder_activate” should be executed. We now create exactly this function in our class.

public function updateReminder_activate(){
		wp_schedule_event(time(), 'daily', 'updateReminderEvent');
	}

After the normal function declaration, we call a WordPress function that adds an event to the WP cron. Explanation of the given parameters:

  1. time() – this parameter sets the current time at the execution time as the start time of our event. If you want to set a specific time for your task, you can specify it as a Unix timestamp.
  2. Execution Interval – WordPress comes with the following intervals:
    1. 'hourly' – Hourly
    2. 'twicedaily' – Twice daily
    3. 'daily' – Every day
    4. But WordPress wouldn’t be WordPress if there weren’t a filter to add more intervals. Cron interval filter
  3. Last but not least, we give a name with which we can hook into the event via an action hook.

However, our current function would register this event every time the plugin was activated. So that we don’t produce duplicates of our event, we should check whether our event already exists. To do this, we add the following IF query to our function.

public function updateReminder_activate(){
		if (! wp_next_scheduled ( 'updateReminderEvent' ) ) {
			wp_schedule_event(time(), 'daily', 'updateReminderEvent');
		}
	}

Step 6: Execute actions on disable plugin

The “good practice” of a plugin developer also includes cleaning up the data produced when deactivating or deleting the plugin. For our use case, we should already deregister the cronjob event upon deactivation.

The “register_deactivation_hook”

Just like when activating the plugin, we should deregister our cron event again when deactivating it and only run this code once. The hook provided for this corresponds to the procedure of the code used for activation, only that we use “deactivation” instead of “activation”.

So we add the following line to our constructor:

register_deactivation_hook( __FILE__, array( $this, 'updateReminder_deactivation' ) );

As with the activation hook, the parameters passed are the path to this file and the name of the function to be executed.

Remove WordPress cron event on disable

To register a cron event, we use the “wp_clear_scheduled_hook” hook.

Before that, however, we create the method specified in the deactivation_hook and check whether the cron event we are looking for exists. If this is the case, we remove it with the hook and the event name just mentioned (or the event-action hook).

public function updateReminder_deactivation(){
		if ( wp_next_scheduled( 'updateReminderEvent' ) ) {
			wp_clear_scheduled_hook( 'updateReminderEvent' );	
		}
	}

Step 7: Give the cronjob event a function

At this point in time, our plugin is already registering/deregistering an event for the WP-Cron. This event can also be reached via an action hook, but we don’t use it yet and therefore don’t run any code regularly.

To change that, let’s create a method within our class.

public function getUpdateStatus(){
}

We hook this method in our constructor, in our event action hook. For this we use a simple call to the “add_action()” method.

add_action('updateReminderEvent', array( $this, 'getUpdateStatus' ) );

Query update status

In our method we now want to query the status of the available WordPress core, plugin and theme updates as an example.

WordPress already provides us with a method for this. We call this method and store the array we get back in a variable.

$status = wp_get_update_data();

Example of the return value:

array (size=2)
  'counts' => 
    array (size=5)
      'plugins' => int 2
      'themes' => int 0
      'wordpress' => int 0
      'translations' => int 1
      'total' => int 3
  'title' => string '' (length=0)

Get email address and blog name

If updates are available, which we can easily query using the “total” value, we would like to inform the admin via email.

For this we first need the e-mail address of the administrator. This is already stored in the options table of the database when WordPress is installed, so we can retrieve this fairly easily and store it in another variable.

Here you can learn more about working with databases in your own WordPress plugins.

In addition, we ask for the website title so that the admin can assign this email to the website if he wants to operate several websites with this plugin.

if ( $status['counts']['total'] != 0 ) {
	$mail = get_option( 'admin_email' );
	$blogname = get_option( 'blogname' );
}

Send an email in WordPress

Now that we have an email address for the recipient of our information, we can send it out. Within our IF query and under the blog name variable, we briefly check whether an e-mail address is also available in our mail variable and then send our information on its way.

if ( is_email( $mail ) != false ) {
	wp_mail(
		$mail,
		'Update Benachrichtigung ' . $blogname,
		'Für deinen Blog "' . $blogname . '" stehen ' . $status['counts']['total'] . ' Updates zur Verfügung.<br>
		' . $status['counts']['plugins'] . ' Plugin Updates<br>
		' . $status['counts']['themes'] . ' Theme Updates</br>
		' . $status['counts']['wordpress'] . ' WordPress Core Updates<br>
		' . $status['counts']['translations'] . ' Übersetzungs Updates',
		'Content-Type: text/html; charset=UTF-8'
	);
}

WordPress also provides us with a method for sending e-mails, to which we only have to give a few parameters. The parameters used in the example are briefly explained:

  1. $mail – the retrieved email address
  2. String for the subject line using our $blogname variable
  3. Multi-line message containing the values ​​of our update status array
  4. Email header information
    1. Content-Type – specification of html
    2. charset – UTF-8 to display umlauts correctly

So if updates are available and an email address is provided, WordPress will now automatically send an email with the information and the administrator will be reminded of their duty. This would look like this (since my WordPress is up to date, I had this email sent to me for the tutorial even without updates):

WordPress update notification emailWordPress update notification email

Congratulations on your first plugin.

The finished plugin code

updateReminder.php

<?php
/*
Plugin Name: Update reminder
Description: Checks for updates and sends mail
Version: 1.0
Author: Tobias Keller
Author URI: https://tobier.de/
*/
defined( 'ABSPATH' ) or die( 'Are you ok?' );

$start_reminder = new UpdateReminder();

class UpdateReminder{

	public function __construct() {

		register_activation_hook( __FILE__, array( $this, 'updateReminder_activate' ) );
		
		register_deactivation_hook(__FILE__, array( $this, 'updateReminder_deactivation' ) );
		
		add_action( 'updateReminderEvent', array( $this, 'getUpdateStatus' ) );
	}

	public function getUpdateStatus(){

		$status = wp_get_update_data();

		if ( $status['counts']['total'] != 0 ) {
			
			$mail = get_option( 'admin_email' );
			$blogname = get_option( 'blogname' );
			
			if ( $mail ) {
				wp_mail(
					$mail,
					'Update Benachrichtigung ' . $blogname,
					'Für deinen Blog "' . $blogname . '" stehen ' . $status['counts']['total'] . ' Updates zur Verfügung.<br>
					' . $status['counts']['plugins'] . ' Plugin Updates<br>
					' . $status['counts']['themes'] . ' Theme Updates</br>
					' . $status['counts']['wordpress'] . ' WordPress Core Updates<br>
					' . $status['counts']['translations'] . ' Übersetzungs Updates',
					'Content-Type: text/html; charset=UTF-8'
				);
			}
		}
	}

	public function updateReminder_activate(){
		if (! wp_next_scheduled ( 'updateReminderEvent' )) {
			wp_schedule_event( time(), 'daily', 'updateReminderEvent' );
		}
	}

	public function updateReminder_deactivation(){
		if ( wp_next_scheduled( 'updateReminderEvent' ) ) {
			wp_clear_scheduled_hook( 'updateReminderEvent' );
		}
	}

}

index.html

<!-- Silence is golden -->

Create a WordPress plugin – no rocket science

Writing WordPress plugins, as you may have noticed, is not that difficult. Due to the popularity of WordPress, you will also find many examples on the Internet for a wide variety of needs. In addition, there is really good documentation on the part of WordPress – the WordPress Codex.

Did you still have unclear points after my tutorial? I’m happy to help you in the comments.