10 crucial wordpress plugin development tips

If you're a Wordpress developer and your looking to get into plugin development - or maybe you just want to play around with some ideas - there are some important considerations when you're releasing your plugin for public launch.

I have recently released my first plugin, EPS 301 Redirects, a plugin that allows you to easily create your own 301s within WordPress, and realized there’s a lot you need to consider.

1. Prefixing

Number one is prefixing (Or a more advanced option is Namespacing, which we will not be talking about today). That is to say, ensure your classes and functions all share a common prefix, this helps for two reasons:

  1. Your functions are readily identifiable as being part of your plugin.
  2. Unique function names reduces the chance of conflicts with other existing functions.

For example, releasing a plugin with a function with what could be considered a common name, get_category_ids, may already exist in someone elses WordPress install, and instantly crash their site. Terrible!

So what’s the best practice here? Well, I like to use an abbreviation of my plugin as my prefix. I just released my first plugin, EPS 301 Redirects, into the WordPress repository, and I used the prefix eps_ for things like Class names, Function Names, Constants, and other declarations which could potentially conflict with other plugins or themes.

2. Debug, Debug, Debug!

When creating your plugin, have WordPress Debugging turned on. To do so, insert this code into your plugin:

define('WP_DEBUG', true);

This will help you iron out any errors or warnings during development. Releasing a plugin that’s spitting our warnings or errors when a developer is debugging their own theme or plugin is a great way to get your plugin deleted.

This also allows you the opportunity to create debugging conditionals in your code which are only visible if WP_DEBUG is on. You can then write a function like:

function my_plugin_view( $data ) {
if ( WP_DEBUG === FALSE ) return false;
   echo '<pre>';
        print_r( $data );
   echo '</pre>';
}

3. Define some globals

This is just an ease of use thing, but define some globals for pieces of data that your plugin accesses frequently, or may change in the future.

define ( 'MY_PLUGIN_PATH', plugin_dir_path(__FILE__) );
define ( 'MY_PLUGIN_URL', plugin_dir_url( __FILE__ ) );
define ( 'MY_PLUGIN_VERSION', 1.1);
define ( 'MY_PLUGIN_NAME', trim(dirname(plugin_basename(__FILE__)), '/')

4.Activation and Deactivation Actions

Often overlooked are these two functions:

register_activation_hook(__FILE__, 'my_plugin_activation'));
register_deactivation_hook(__FILE__, 'my_plugin_deactivation'));
function my_plugin_activation() {
// Initialize some stuff for my_plugin
}
function my_plugin_deactivation() {
// Welp, I've been deactivated - are there some things I should clean up?
}

5. Live up to Coding Standards

Everyone has their quirks and personality when it comes to writing code, however, it is super important when developing a plugin for public release to follow WordPress coding standards.

You should pay close attention to these points:

  • Comments: Comment, even when your intentions might seem obvious, use comments to outline what it is you’re doing, or why you made certain logical decisions. You might thank yourself later when going back to do some updates!
  • Naming Conventions: Do you prefer camelCase or under_scores? Whichever you chose, just use it consistently. I personally use underscores for functions and variables. Classes are Title_Cased, constants are ALL_CAPS, private methods are prefixed with underscores _private_function. Though, to each their own!

6. Security

This is a massive topic; and you should NOT overlook it, or take it lightly. Security holes have some serious ramifications – does anyone remember the timthumb debacle?

It’s too large a topic to go into for this post – but WordPress has built in functions you should be using whenever you display data which could potentially be at risk:

Also, when validating user inputs, run these PHP filters:

Nonces are also an important consideration; Nonces can be used to ensure form submissions are coming from an expected source. Use them in every form you create, and validate them.

Insert this PHP into your form:

wp_nonce_field('my_plugin_nonce', 'my_plugin_nonce_submit');

And validate it in your handler like so:

if ( !wp_verify_nonce( $_POST['my_plugin_nonce_submit'], 'my_plugin_nonce') ) return false;
My last piece of advice is to USE NATIVE WORDPRESS FUNCTIONS to do ANYTHING with the database. Get VERY familiar with the $wpdb class, and use PREPARED statements whenever you can. Keep in mind that some WordPress functions will sanitize and escape data for you (like wp_insert_post, or $wpdb->insert), but others may not.

7. Database Interactions

Again USE NATIVE WORDPRESS FUNCTIONS to do ANYTHING with the database. When Querying or Inserting avoid explicitly stating table names, and even moreso, try to use WP_Query() instead of SQL statements like SELECT * FROM {$wpdb->prefix}_posts.

8. Hooks

Depending on the scope of your plugin, you should consider adding your own custom hooks for future developers to extend your plugin.

9. Resources

Load resources sparingly; use wp_enqueue_script and wp_enqueue_style. And only enqueue your resources when you need them, for example if your plugin needs some Javascript for an admin page, use something like the below to ensure you’re not loading it when it’s not needed.

if ( is_admin) {
wp_enqueue_script( 'your_javascript', $file_url );
}

Of course you can go EVEN further, and only load resources on certain pages:

global $pagenow;
if ( ( $pagenow == 'edit.php' ) ) {
wp_enqueue_script( 'your_javascript_only_on_edit_pages', $file_url );
}

Or, only on certain custom post types, taxonomies… whatever, you decide!

10. Document Blocks

Document blocks, and to a lesser extent function or class blocks are good ways to keep your functions organized and well documented, here are some basic templates you can use in your plugin.

Functions:

/**
* FUNCTION NAME
* Does something interesting
*
* @param $string_var (string) Describe what this is and what its for.
* @param $int_var (int) Describe what this is and what its for.
* @return $data What does this function return? (if anything)
*/

Classes:

/**
* CLASS NAME
* Short description for class
*
* Long description for class (if any)...
*
* @copyright Your copyright information
* @version Release: XX
* @link More information can be found at this web url...
* @since Available Since XXXX
* @license Your license information
*/

Documents:

/**
* DOCUMENT NAME / PROJECT NAME
* Short description
*
* Long description (if any)...
*
* @copyright Your copyright information
* @version Release: XX
* @link More information can be found at this web url...
* @since Available Since XXXX
* @license Your license information
* @author Your Name ( you@youremail.com )
*/