wordpress

Getting Started Writing WordPress Plugins


     Getting Started Writing WordPress Plugins

Posted June 1st, 2009 / By Douglas Neiner in Frameworks, PHP, Plugins / Add-Ons

Why WordPress?

For those who use WordPress on a daily basis, this is a no-brainer. However, as everyone seems to have their own pet CMS, it is sometimes hard for them to understand why anyone would use WordPress for something other than just a blogging platform. I am sure there are many pros and cons, but I will just give my personal answer: I feel very comfortable using and pushing the limits of WordPress for projects because of the huge install and developer base, the active development work being done, the amount of documentation available to my client, and the extensibility and integration my code has with the WordPress core.

Why WordPress Plugins?

A WordPress plugin can be a single PHP file or a complex collection of PHP, CSS, JS and images all used together to add new or enhanced functionality to the WordPress core.

Since almost everything you can put in a plugin you can also just dump into a functions.php file in your theme directory, why should you bother building a plugin? Here are a few reasons I find important:

  • Plugins are focused pieces of code structured to accomplish one task. The very nature of a plugin makes it easy to maintain.
  • Because of the modular nature of a plugin, it makes your code instantly reusable on other projects (Depending on your code ownership agreements with your clients, of course.)
  • If over time it grows into a truly helpful collection of code, having it in a plugin allows you to release it to the public quickly and easily.
  • Having large chunks of functionality split into plugins makes changes to the PHP and related files easier to make later.

I think WordPress plugins should be especially important to anyone running a web application that could benefit from direct integration into the WordPress platform. This could include a WordPress sidebar widget that pulls information from your website, a shortcode for quickly embedding your site content in WordPress posts, etc.

wordpress_plugins

Getting Started

File Naming

The first choice you should make is whether you need a single PHP file or a folder with multiple files and assets. Here are some questions help you think through this:

  • Am I going to have associated images, CSS, or JS related to this plugin
  • Will I have more than one admin panel needed for users to manage this plugin
  • Will there be multiple distinct pieces to this plugin (i.e. widgets, template tags, etc).

If you are building anything more than a simple plugin with a few methods and no associated files, you should go with a directory structure for your plugin.

If we were going to build a plugin called “Fancy Plugin,” your file would look like this:

wp-content/plugins/fancy_plugin.php

or

wp-content/plugins/fancy_plugin/fancy_plugin.php

Keep in mind when you name your plugin file that it is unique to what your plugin is and does. Since two plugins cannot both be installed if they have the same file name, be sure to run a Google search and check the Extend section of WordPress.org before settling on a name.

Folder Structure

For complex plugins, I follow this format for my directory structure:

plugin_folder/
-- plugin_file.php  <= Primary Plugin File
-- css/             <= All CSS
-- images/          <= All Images
-- js/              <= All JS
-- php/             <= Supporting PHP Files
-- views/           <= All Administrative Panels and Metaboxes

Plugin Metadata

The very first thing you need in your plugin is the metadata block that is used by WordPress to both activate your plugin and notify the user of pertinent information. It should look like this (Taken directly from “Writing a Plugin”:

<?php
/*
    Plugin Name: Name Of The Plugin
    Description: A brief description of the Plugin.
    Version: The Plugin's Version Number, e.g.: 1.0
    Author: Name Of The Plugin Author
    Author URI: http://URI_Of_The_Plugin_Author
*/
?>

This metadata block is a simple cut and paste into your primary plugin PHP file.

Extending WordPress With Your Plugin

Template Tags

One of the most simple things your plugin can do, is offer custom template tags for use in your themes. Template tags are just PHP functions. A good rule of thumb is to follow the direction of the WP team by prefixing functions that return data with get_, and functions that echo out directly with the_. For example:

function get_map_widget_code(){
    return "<script src='...'>My really long widget code...</script>";
}
function the_map_widget_code(){
    echo get_map_widget_code();
}

These functions could then be used in any theme like this:

<p>The two ways to use these template tags are echo it myself:</p>
<?php echo get_map_widget_code() ?>
<p> or let the function echo it (cleaner): </p>
<?php the_map_widget_code() ?>

Template Tags, like all top level functions, have to be unique across the entire set of plugins, WP Core, and theme files. Be sure to choose names that are unique enough as not to conflict with existing method names.

Shortcodes

Shortcodes were introduced in WordPress 2.5 and allows the programmer to solve some complex HTML problems in an extremely easy way. Perhaps you want to provide an easy way for a client to list a few products on any page or post. You could just give them the HTML, and tell them to be sure to copy it anywhere they want products… but we all know how well instructions like those work out. Instead, you should provide a simple short code for them to use:

[products]
[product name="My Special Product" price=3.99]
[product name="An Amazing Book" price=12.99]
[/products]

That is a lot easier for a client to remember than a bunch of nested HTML that they have to switch into HTML view to edit or create. Here is the PHP code that would allow this shortcode to function:

function products_shortcode_callback( $atts, $content=null ){
    // Set a blank return by default
    $ret = "";
    // If there is content between the shortcodes
    // then add our wrapping tags
    if($content){
        $ret = '<ul>';
        // Nested shortcodes are not processed by default
        // be sure to make this call if you want
        // to process nested shortcodes
        $ret .= do_shortcode($content);
        $ret .= '</ul>';
    }
    // Never echo output from a shortcode function!!!
    return $ret;
}
function product_shortcode_callback( $atts ){
    // Get the attributes and filter out
    // unwanted attributes
    $a = shortcode_atts( array(
        'name' => 'Product Name',
        'price' => 'No Price'), $atts );
    // Prepend a $ sign if price is supplied
    if ($a['price'] != 'No Price') $a['price'] = '$' . $a['price'];
    // Build HTML
    $ret = "<li><span class='product-name'>";
    $ret .= $a['name'] . "</span><br />";
    $ret .= '<span>' . $a['price'];
    $ret .= '</span></li>';
    // Again, return NOT echo:
    return $ret;
}
// Finally, add the shortcodes to the system
// So WordPress knows about them
add_shortcode( "products", "products_shortcode_callback" );
add_shortcode( "product", "product_shortcode_callback" );

As you have seen twice in the comments of the previous code example, NEVER echo output from a shortcode! Be sure to always return the content so it can be inserted in the correct place.

The previous code example would replace the shortcodes with this HTML (lines split for clarity):

<ul class="products in-post-products">
<li><span class="product-name">My Special Product</span><br /><span class="price">$3.99</span></li>
<li><span class="product-name">An Amazing Book</span><br /><span class="price">$12.99</span></li>
</ul>

Reference Links

Filters and Actions

Much of your extensions to the WordPress core will happen with Filters and Actions. Thankfully, they are pretty easy to understand! A filter simply sends you content at the appropriate time, and expects content in return. Be sure to check the documentation on WordPress.org when creating filters because certain filters will pass you more than one parameter. The following code will add text before and after each post title:

function add_text_to_title( $title ){
    return 'Text Before << ' . $title . ' >> And After';
}
// Register filter with WP
add_filter( "the_title", "add_text_to_title" );

Actions are called when certain actions are about to happen or have just happened. Actions allow you to execute your code at the appropriate time. The following code adds a javascript file to each page of the front-end site:

function add_special_scripts(){
    wp_2_enqueue_script(
        'special_script',
        plugins_url('/test/special.js'),
        array( 'jquery' ), // require jquery
        '0.1' // Helps with cacheing
    );
}
// Register the action with WP
add_action("wp_2_print_scripts", "add_special_scripts");

Reference Links

Widgets, Pluggable Functions, Settings, and User Interaction

Some of the more advanced techniques of building plugins, including user interaction through admin menus, storing settings in the database, and writing a sidebar widget will be covered in an upcoming article.

Closing Advice

  1. When you begin to extend WordPress through plugins or theme additions, make the Codex your best friend. The amount of developer documentation availible is amazing and extremely helpful.
  2. If you cannot find documentation on a particular function or hook, do a global search of your WordPress installation (Cmd+Shift+F in TextMate) to look for the definition of the function. Often looking at the source will give you an idea how it works.
  3. Make sure you have PHP errors turned on locally, or have access to your PHP error log to troubleshoot your development. Not being able to catch small PHP errors can make your life miserable.

Doug Neiner is an Editor at Fuel Your Coding and an official member of the jQuery Team. He is addicted to new technology, and specifically loves spending time with WordPress, Ruby on Rails and jQuery. Learn more via twitter or his Google Profile.

Leave a comment