New Site

I just recently changed web hosts, and am taking this opportunity to do some much-needed house cleaning.  I will be getting my old content back up in the next few days.  Meanwhile, whaddya think of the new look?

Getting Started – WP Plugins Part 1

So, you’re ready to dive into writing a WordPress plugin, huh?  Great!  This series is intended as a guide for developers who are fairly experienced with PHP, but not necessarily with the intricacies of WordPress.

Throughout this series, I’ll be writing a sample plugin, called Simple Guestbook.  The goals of this plugin are, well,  simple.  I want to provide a Guestbook form that can be placed anywhere on the site with the a shortcode.  I want to provide a widget that will show recent submissions.  And I want to provide an admin interface to manage Guestbook submissions.  These goals will allow us to cover a lot of the basic features provided by plugins.  Let’s get started.

Create your plugin files

Writing a WordPress plugin can be fairly simple, or fairly complex, depending on what the needs of the plugin are.  At its simplest, a plugin can be a single file, in WP’s plugins/ directory.  But usually a plugin contains several (or sometimes dozens or hundreds) of files.  So, it’s usually best to put all the plugin files in a subdirectory.  For our plugin, we’ll start with the following structure:

  1. wp-content/plugins/guestbook/
  2. wp-content/plugins/guestbook/guestbook.php
wp-content/plugins/guestbook/
wp-content/plugins/guestbook/guestbook.php

Put something in them!

We don’t quite have a plugin yet.  We have to go one step further, and give our plugin some meta-data.  We do that by creating a PHP comment block in our plugin’s main file — guestbook.php.  Like so:

  1. <?php
  2. /*
  3. Plugin Name: Simple Guestbook
  4. Plugin URI: http://www.mkeasling.com/simple-guestbook
  5. Description: A sample plugin built for a plugin-writing tutorial.
  6. Version: 0.1
  7. Author: Matthew Keasling
  8. Author URI: http://www.mkeasling.com
  9. */
<?php
/*
Plugin Name: Simple Guestbook
Plugin URI: http://www.mkeasling.com/simple-guestbook
Description: A sample plugin built for a plugin-writing tutorial.
Version: 0.1
Author: Matthew Keasling
Author URI: http://www.mkeasling.com
*/

You’ve got a fully-functioning plugin!  You can activate it, deactivate it, remove it, whatever you want!  Exciting, right?!

OK, well maybe not exciting…  not yet, at least.  But it’s a good start.  Moving along….

Let’s prepare for the real work

OK, we’ve got a working plugin, but it doesn’t do anything yet.  Like, not anything.  That’s just no fun.  Pretty soon, we’re going to have to start adding functionality.  Well, one way we can do that is just by adding code to guestbook.php.  Many plugins you’ll see do just that.  However, I’m going to advise against it, because as the plugin grows more complex, the single-file approach gets to be pretty unmaintainable downright ghastly.  So, I’ll create another subdirectory called includes/.  Our directory structure now looks like this:

  1. wp-content/plugins/guestbook/
  2. wp-content/plugins/guestbook/guestbook.php
  3. wp-content/plugins/guestbook/includes/
wp-content/plugins/guestbook/
wp-content/plugins/guestbook/guestbook.php
wp-content/plugins/guestbook/includes/

I’ve chosen to put other files in a subdirectory because it makes it very clear exactly which file is the main plugin file–namely, the only file directly in the plugin’s directory.  This helps us humans, but it also helps WP by not having to inspect extra files to see which one has the Plugin docblock we discussed earlier.

Let’s remember where we are

This won’t become evident until later in the tutorial, but in several places, WordPress will require you to know the location of your plugin files.  Because we’re getting a little fancy here, we can’t always rely on some basic PHP conventions like dirname(__FILE__).  So, in this main file, we’re going to create some functions that we can use later.

  1. // sgb : Simple GuestBook
  2. function _sgb_file() { return str_replace(WP_PLUGIN_DIR.DIRECTORY_SEPARATOR,'',__FILE__); }
  3. function _sgb_uri(){ return dirname(__FILE__); }
  4. function _sgb_url(){ return plugins_url('', __FILE__); }
// sgb : Simple GuestBook
function _sgb_file() { return str_replace(WP_PLUGIN_DIR.DIRECTORY_SEPARATOR,'',__FILE__); }
function _sgb_uri(){ return dirname(__FILE__); }
function _sgb_url(){ return plugins_url('', __FILE__); }

We can use these functions anywhere in our plugin code, and be assured that they’ll return the file name, file location, and url, respectively, of our main plugin file/directory.

[box type='info']
An important note here: our main plugin file simply gets included into the running page.  So, any variables or functions that we declare in it will be in the same global namespace as any variables declared elsewhere in WP and in other plugins.  And, since you don’t know what other plugins your users might have, it’s best to name these in a way that will be unique to your plugin.  In this case, I created a prefix, sgb, that I’ll use throughout to help avoid any conflicts.
[/box]

Conclusion

Okay.  After this first part of the tutorial, we have created our plugin, and created a directory structure that will allow us to create as many additional files as we need.  We’ve made sure that we’ll always remember where we came from, which will come in handy later, when we start adding filters and hooks and WP demands to know.

In the next part of the tutorial, we’ll start adding some real functionality!  Meanwhile, here’s a file showing what we’ve got so far: GuestBook App – Part 1

See you in the next tutorial!

Writing a WordPress Plugin Series

[mkc_block id=80]

I’ve had a lot of work lately writing custom WordPress plugins for clients.  This has been fairly new to me, so it’s been interesting to learn about all the different aspects of plugin authoring.  So, both as help to others going through this, and also as a consolidated reference for myself, I’m going to document the process and all its various steps.  So here’s the general outline of what I plan to write: (links will get filled in as I write them)

  1. Getting Started
    Directory structure & File Basics
  2. Shortcodes
    Those handy little things that allow your plugin to work just about anywhere
  3. Templates
    Bonus Feature! – I, for one, hate embedding HTML in PHP code.  So, I took the time to add a template engine into my plugin.
  4. Widgets
    For when your plugin doesn’t have to work just anywhere
  5. Admin Pages
    Settings, Managing Data, etc.
  6. Putting it out there
    Activation/Deactivation Scripts,  Packaging, etc.

Not all plugins will use all of these things.  Maybe your plugin doesn’t need to offer a shortcode, or a settings page.  Feel free to ignore those portions of the series.  But hopefully, this will be comprehensive enough to cover most of your basic plugin-writing questions.  As I continue learning and working, I’ll probably continue adding to this series.  There are many more plugin capabilities than just what are listed above.  So, hopefully, you’ll see this list grow over time.

Meanwhile, let’s get started with Part 1!

Javascript Callbacks

I recently had a site loading really slowly, and I had to do some refactoring to load things differently.  I had the basic page, and then a bunch of extra information that needed to be available in lightboxes.  I didn’t want the basic page to be slowed down by the 500K+ of lightbox information, but I also didn’t want each lightbox to take 1-2 seconds to load on click.  So, I decided to start pre-fetching the lightbox information as soon as the page finished loading.

At first, this seemed easy enough.  1) load the data.  2) when it’s done, allow the lightboxes to work.  Easy, right?

Wrong.

What if it takes 5 seconds to load all the lightbox data, and a user is clicking on things before it’s all loaded?  No response whatsoever for 5 seconds.  Bad.

Next plan: 1) load the data. 2) allow the lightboxes to show, with a loading image, until the data is ready.  Easy, right?

Wrong.

In my particular case, I had to do some jQuery fanciness after showing the lightbox, to make sure the right data was showing, and was properly formatted.  Where I had been relying on the data to be there already, and using the click event as the only trigger for my formatting function, I was now faced with having a click event that might not have data to format yet.

So, here’s where the complexity came in.  Either the data will load before the user clicks anything, and it needed to show the default data, OR the user will be faster than the server and will expect the data to reflect what they clicked on, rather than the default.

The solution?  Define the post-load callback function as a variable.  If the user fires a click event, simply re-define the variable.

Here’s some sample code, to show what I mean:

  1. jQuery(document).ready(function($){
  2.   // hold our callback function. can be redefined from anywhere.
  3.   var prepare_item_callback = function(){ $('#lightbox div:first').prepare(); };
  4.   // if the data isn't loaded yet, this function will load the data then run the callback
  5.   // if the data is ready, it will run the callback immediately
  6.   function prepare_lightbox(){
  7.     if($("#lightbox").hasClass("data-loaded")) return prepare_item_callback();
  8.     $("#lightbox").load('/my/lightbox/source',function(status){
  9.       if(status=='success'){
  10.         $("#lightbox").addClass("data-loaded");
  11.         prepare_item_callback();
  12.       }else{
  13.         $("#lightbox").addClass("data-error");
  14.       }
  15.     });
  16.   }
  17.   // use click event to redefine callback
  18.   $(document).delegate('#lightbox div','click',function(){
  19.     // here, we want the callback to both prepare and Show the lightbox
  20.     prepare_item_callback = function(){ $(this).prepare().show(); };
  21.     prepare_lightbox();
  22.   });
  23.   // let's pre-load the lightbox data
  24.   prepare_lightbox();
  25. });
jQuery(document).ready(function($){
  // hold our callback function. can be redefined from anywhere.
  var prepare_item_callback = function(){ $('#lightbox div:first').prepare(); };
  // if the data isn't loaded yet, this function will load the data then run the callback
  // if the data is ready, it will run the callback immediately
  function prepare_lightbox(){
    if($("#lightbox").hasClass("data-loaded")) return prepare_item_callback();
    $("#lightbox").load('/my/lightbox/source',function(status){
      if(status=='success'){
        $("#lightbox").addClass("data-loaded");
        prepare_item_callback();
      }else{
        $("#lightbox").addClass("data-error");
      }
    });
  }
  // use click event to redefine callback
  $(document).delegate('#lightbox div','click',function(){
    // here, we want the callback to both prepare and Show the lightbox
    prepare_item_callback = function(){ $(this).prepare().show(); };
    prepare_lightbox();
  });
  // let's pre-load the lightbox data
  prepare_lightbox();
});

For seasoned JavaScript developers, this probably seems like a no-brainer.  For a primarily-PHP guy, though, this was mind-blowing awesomeness.  Changing behavior mid-stream, based on real-time data, as simple as changing a variable.  I’m beginning to like this JavaScript stuff…

Have you encountered any similar situations? How did you resolve them? Think this approach is great? Think it sucks? Let me know…

Introduction

Hi there.

I work full-time as a programmer, and I’m constantly learning new things. Sometimes, I’m lucky enough to stumble on what I need to know by searching for others who’ve had the same problems. Sometimes, I can’t find what I need to know, and have to figure it out the hard way. Well, for as much as I gain by learning from others, I’m hoping that maybe I can use this blog to pay it forward.

I doubt this blog will often contain earth-shattering new concepts, or mind-blowing insights. But hopefully, at some point, it will be a handy resource to some other programmer in need.