Advertisement
  1. Code
  2. WordPress

Anatomy of a WordPress Plugin

Scroll to top
Read Time: 13 min

WordPress is well known for its amazing collection of free plugins. There is one for almost every need
you can think of, from backing up your WordPress installation to asking for a cup of coffee
or fighting spam.

But there are times when none of the available plugins seem to quite do the trick you are looking for. To help you in moments like
that, this tutorial will guide you through every step of building a simple, widgetized WordPress plugin with settings.

Writing your own plugin is not rocket science reserved for the most savvy programmers. All you need
is a basic understanding of
the PHP programming language
and some information on how WordPress expects your plugin to behave. This tutorial will provide you with the latter.

The Goal

Before we get started, let me introduce the concept of the plugin and what we are trying to achieve with it.

"Coming Next" will be a widget plugin that queries a given number of blog posts scheduled for the future and lists them in the blog's sidebar (or where ever
the blog owner decides to place the widget). The widget will be customizable so that the user can decide how many posts he wants to list,
if a summary of the post should be shown, and what the date format should be. The looks of the widget should be easily customizable through CSS.

Here is a quick drawing of how the widget could look like in action:


Let's get started!

Step 1: The Plugin Template

Plugins in WordPress are PHP files that have been put in the wp-content/plugins directory under the WordPress installation directory.

For simple plugins that fit nicely in just one file, like the one we are creating today, it's enough to create a single PHP file and upload it to the
plugin directory. It is, however, a good practice to always create a separate directory for every plugin and that way help the blog owners keep their plugins
organized. This will also make it easier to expand your plugin if you ever need to add new files to it.

Let's create a directory for the "Coming Next" plugin:



Created directory: /wp-content/plugins/coming-next

In this new directory, we then create the plugin's main PHP file. Let's call it coming-next.php.

When searching for plugins, WordPress goes through each file inside the plugin directory looking for comments that identify the files as plugins. That
comment section tells basic information about the plugin and at the bare minimum needs to contain the name of the plugin.

Here's how the comment block for our "Coming Next" plugin will look like:

1
2
<?php
3
/*

4
Plugin Name: Coming Next

5
Plugin URI: https://code.tutsplus.com

6
Description: Shows the next scheduled posts with brief descriptions. 

7
Version: 1.0

8
Author: Jarkko Laine

9
Author URI: http://jarkkolaine.com

10
*/
11
?>

Save the file and go to the plugins page in your WordPress admin area. The plugin, with all the information added in the comment,
is already visible in the the plugin list:



This is how the plugin appears on the plugin list

You can already activate the plugin, but as we haven't yet put in any code, nothing will happen. We need some functionality.

Step 2: Adding Functionality

In its simplest form, a WordPress plugin is nothing more than one or more functions put inside a plugin file.

All functions created in plugins are visible to both the current theme and other active plugins, so it is possible to

use the plugin system to extend the platform with new functions and then just call them straight from your theme.

Let's do that first and create the function at the core of the "Coming Next" plugin, list_upcoming_posts().

One word of warning is in place before we start: Because all functions added in plugin files will be visible throughout your
WordPress installation, you need to be very careful when naming them. If there are two functions with the same name
in two (or more) different plugins, they will conflict, and things just cannot work.

For larger plugins it's a good idea to do some object oriented programming and create classes to encapsulate parts
of the functionality. That will give you more freedom in naming your functions and variables. In smaller plugins like
this one, you just need to be careful, and try to use descriptive function names that you think no one else is using.

1
2
function list_upcoming_posts($num_posts = 1, $show_excerpt = false, 
3
                             $text_format = "Coming Up on [date]") {
4
  $posts = get_posts("numberposts=".$num_posts."&order=ASC&post_status=future");
5
6
  echo "<ul class=\"upcoming-posts\">";
7
  global $post;
8
  $old_post = $post;
9
10
  foreach ($posts as $post) :
11
    setup_postdata($post);
12
    $my_date = the_date('', '', '', FALSE);
13
    $coming_up_text = str_replace("[date]", $my_date, $text_format);
14
  ?>
15
    <li class="upcoming-post">
16
      <span class="upcoming-post-date"><?php echo $coming_up_text; ?></span>
17
      <span class="upcoming-post-title"><?php the_title(); ?></span>
18
      <?php if ($show_excerpt) : ?>
19
        <span class="upcoming-post-description">
20
          <?php the_excerpt_rss(); ?>
21
        </span>
22
      <?php endif; ?>
23
    </li>
24
  <?php
25
  endforeach;
26
27
  $post = $old_post;
28
  setup_postdata($post);
29
  echo "</ul>";
30
}

This function uses the get_posts() WordPress
function to retrieve as many future posts as specified in the $num_posts parameter, or all future posts
if $num_posts is greater than the actual number available.

Then it renders a list including the titles of the posts, their scheduled dates, and the excerpt of the post if $show_excerpt is set to true.

Note that we need to use the global $post variable to setup the post data (see line 10) for function calls such
as the_title() to work. Now, in case the blog template needs access to the current post after rendering the plugin,
we need to put back the original post once we are finished (see lines 7, and 26-27). Otherwise, the rest of the content would be rendered using the last
post that was set up using setup_postdata().

Congratulations! You have just written your first WordPress plugin and can test it by adding this call somewhere in your blog template:

1
2
<?php
3
if (function_exists("list_upcoming_posts")) {
4
  list_upcoming_posts();
5
}
6
?>

Create a post titled "Back to the Future" and schedule it to appear on your blog on January 1st, 2020. Here's what you should see:



The Plugin in action. Without any CSS styling yet.

Step 3: Making the Widget

For some plugins, just having a function you can call from your theme is more than enough. But for this plugin, I think letting the user
customize the output through his WordPress admin page will provide a nice final touch. And the WordPress widget system is the perfect way to
achieve that level of user-friendliness.

In case you aren't yet familiar with the concept of WordPress Widgets,
here's what the WordPress documentation says about them:

WordPress Widgets allow the easy addition of design elements, gadgets, content, images, and more to your WordPress sidebar to personalize
your blog without knowing HTML, PHP, or any code. Many WordPress Plugins now come with a Widget version to allow easy addition to the sidebar.

If your theme supports widgets, you can go to the Widgets tab in the Design section of your WordPress admin area and assign widgets to the different
positions that the theme designer has created for them:



The "Widgets" settings screen

To make our "Coming Next" plugin work as a widget, we first need to create a function for rendering the widget. As we can reuse the
list_upcoming_posts() function we created earlier, this task will be rather straightforward.

Here is the code for the widget in its simplest form:

1
2
function widget_coming_next($args) {
3
  extract($args, EXTR_SKIP);
4
  echo $before_widget;
5
  list_upcoming_posts();
6
  echo $after_widget;
7
}

All the function does is that it extracts the HTML markup that the theme designer has set up to be rendered before ($before_widget) and
after ($after_widget) every widget, and then renders it around the list of upcoming posts.

The extract() function is standard PHP.
It takes the fields from the given array ($args) and creates local variables out of them. Another way of
doing the same would have been to reference the array directly using "before_widget" and "after_widget" as array indices.

Now, the widget knows how to render itself. But before it can be added to a blog, we still need to tell WordPress to add it to the list
of widgets on the administration page. This is done by creating an initialization function that registers the sidebar widget and adding
a plugin hook to call that function after all WordPress
plugins have been loaded into memory.

1
2
function widget_coming_next_init() {
3
  wp_register_sidebar_widget(COMING_NEXT_WIDGET_ID, 
4
  	__('Coming Next'), 'widget_coming_next');
5
}
6
7
// Register widget to WordPress

8
add_action("plugins_loaded", "widget_coming_next_init");

The initialization function calls wp_register_sidebar_widget()
to register the widget to WordPress. The function needs three parameters: a unique identifier for the widget, a name to be used on the Widgets
page in the admin area and the name of the function that will render the widget.

To make things easier, if we ever need to change the unique identifier, I have created a constant for it. This way, when we use the same constant everywhere,
we will only have to update it in one place. Add this constant definition at the beginning of the widget file, right after the comment block that identifies the plugin:

1
2
define(COMING_NEXT_WIDGET_ID, "widget_coming_next");

Now, when you go to check out the "Widgets" page, you'll see the new widget there waiting to be added on the blog. And when you add
the widget to a widget position, you'll see the upcoming posts appear right where you put them!



The "Coming Next" widget has now been added to the widget list.

Step 4: Widget Settings

Finally, to complete the plugin, we will create a settings menu for updating the widget preferences. The settings box will contain all the same
parameters that the list_upcoming_posts() function takes as paramters. As that function has already been done and
it knows how to handle the parameters, all that is left is building the settings menu and making it save and retrieve the settings.

Just like for the widget rendering, we will create a function that renders the settings menu and stores the settings
in the persistent storage, and then tell WordPress about the function so that it knows to show it when adding or editing the widget.

Here's the code for storing and retriving the settings:

1
2
function widget_coming_next_control() {
3
  $options = get_option(COMING_NEXT_WIDGET_ID);
4
  if (!is_array($options)) {
5
    $options = array();
6
  }
7
8
  $widget_data = $_POST[COMING_NEXT_WIDGET_ID];
9
  if ($widget_data['submit']) {
10
    $options['num_posts'] = $widget_data['num_posts'];
11
    $options['coming_up_text'] = $widget_data['coming_up_text'];
12
    $options['show_excerpt'] = $widget_data['show_excerpt'];
13
14
    update_option(COMING_NEXT_WIDGET_ID, $options);
15
  }
16
17
  // Render form

18
  $num_posts = $options['num_posts'];
19
  $coming_up_text = $options['coming_up_text'];
20
  $show_excerpt = $options['show_excerpt'];
21
  
22
  // The HTML form will go here

23
}

The heart of this function are these two calls to the WordPress API:
get_option() on line 2 and
update_option() on line 13.
update_option() can be used to save any variable to the WordPress database as a key-value pair and get_option to
read it.

For example, in the above code snippet, you'll see that on line 13, update_option() is used to store the $options array with the
key COMING_NEXT_WIDGET_ID.

To make things more organized, instead of saving each variable as a separate key-value pair, we put them in an
array ($options) that can be saved at one go.
This array then holds all the data related to this widget. The array is loaded at the beginning of the function so that the data is available
for rendering the settings form and the existing settings can be used as form defaults and won't get lost when the form gets submitted.

The widget_coming_next_control() function gets called both when the settings form is first shown and when the user presses the "Save Changes" button
to store the settings. To identify whether the form has been submitted or not, we use a hidden field
called COMING_NEXT_WIDGET_ID[submit]. If the hidden field has been saved, we read in the parameters from the
form and save them (lines 8-14). And in both cases, whether data is saved or not, the form is rendered.

Speaking of forms, that core part is still missing. Copy the form below and put it at the end of the function we just created
(right after line 21, before the closing brace):

1
2
?>
3
<p>
4
  <label for="<?php echo COMING_NEXT_WIDGET_ID;?>-num-posts">
5
    Number of posts to show:
6
  </label>
7
  <input class="widefat" 
8
    type="text"
9
    name="<?php echo COMING_NEXT_WIDGET_ID; ?>[num_posts]" 
10
    id="<?php echo COMING_NEXT_WIDGET_ID; ?>-num-posts" 
11
    value="<?php echo $num_posts; ?>"/>
12
</p>
13
<p>
14
  <label for="<?php echo COMING_NEXT_WIDGET_ID;?>-coming-up-text">
15
    "Coming Up Next" text (use the [date] tag to 
16
    display the publish date):
17
  </label>
18
  <input class="widefat" type="text" 
19
    name="<?php echo COMING_NEXT_WIDGET_ID; ?>[coming_up_text]" 
20
    id="<?php echo COMING_NEXT_WIDGET_ID; ?>-coming-up-text" 
21
    value="<?php echo $coming_up_text; ?>"/>
22
</p>
23
<p>
24
  <label for="<?php echo COMING_NEXT_WIDGET_ID;?>-show-excerpt">
25
    Show excerpt:
26
  </label>
27
  <select class="widefat"
28
    name="<?php echo COMING_NEXT_WIDGET_ID; ?>[show_excerpt]"
29
    id="<?php echo COMING_NEXT_WIDGET_ID;?>-show-exceprt">
30
    <option value="1" <?php echo ($show_excerpt == "1") ? "selected" : ""; ?>>
31
      Yes
32
    </option>
33
    <option value="0" <?php echo ($show_excerpt == "1") ? "" : "selected"; ?>>
34
      No
35
    </option>
36
  </select>
37
</p>
38
<input type="hidden" 
39
  name="<?php echo COMING_NEXT_WIDGET_ID; ?>[submit]" 
40
  value="1"/>
41
<?php

If you look at the form carefully, you will notice that there are no form opening or ending tags. This is because all active widgets are
put in the same form, rendered by WordPress, and are saved at one press of "Save Changes." This will be useful when you decide to write
a widget that can be added many times, such as the WordPress text widget (when doing that you will need to be aware of multiple widgets
and all their different states at the same time). But for now, it just means that you need to be careful with how you name the fields in your part of the form.

In this plugin, I decided to use the COMING_NEXT_WIDGET_ID constant as an identifier to define which of the fields belong to this widget.
Using the widget_id[field_id] notation in the name parameters of our input tags makes things
nice for us as they get parsed into an array with field_id as the array index.

After creating the settings screen function, we still need to tell WordPress to use it. This is done with the following hook.
Add it to the widget_coming_next_init() function we created earlier:

1
2
  wp_register_widget_control(COMING_NEXT_WIDGET_ID, 
3
      __('Coming Next'), 'widget_coming_next_control');

Now, when you go to add or edit the widget, you'll see that new options have appeared:



The widget now has settings

Last but not least, we will make the widget rendering use the settings defined in the settings box. It's really quite simple: all we need to
do is to read the settings using the get_option() function. Replace the previously created widget rendering function with
this new version:

1
2
function widget_coming_next($args) {
3
  extract($args, EXTR_SKIP);
4
  $options = get_option(COMING_NEXT_WIDGET_ID);
5
6
  // Query the next scheduled post

7
  $num_posts = $options["num_posts"];
8
  $show_excerpt = $options["show_excerpt"];
9
  $coming_up_text = $options["coming_up_text"];
10
11
  echo $before_widget;
12
  list_upcoming_posts($num_posts, $show_excerpt, $coming_up_text);
13
  echo $after_widget;
14
}

That's it. You have now created a WordPress widget with settings!
The output still looks rather dull, but with a small touch of CSS, it'll come alive and be a perfect match to your blog theme.



The Coming Next widget live in action
Advertisement
Did you find this post useful?
Want a weekly email summary?
Subscribe below and we’ll send you a weekly email summary of all new Code tutorials. Never miss out on learning about the next big thing.
Advertisement
Looking for something to help kick start your next project?
Envato Market has a range of items for sale to help get you started.