Starting a community wiki to collect up objective best practices for plugin development. This question was inspired by @EAMann's comments on wp-hackers.

The idea is to collaborate on what objective best practices might be so that we can potentially eventually use them in some community collaboration review process.

UPDATE: After seeing the first few responses it becomes clear that we need to have only one idea/suggestion/best-practice per answer and people should review the list to ensure there are no duplicates before posting.

link|improve this question
show 2 more comments
feedback

37 Answers

1 2

Use wp options for plugin output strings

In order to make the plugin easily used and customizable, all the output strings should be modifiable. The best way to do that is use wp-options to store the output strings and provide backend to change the default values. Plugin shouldn't use displayed strings that cannot be easily changed using the plugin backend.

For example: Sociable - gives you the ability to change the sentence that appears before the icons part "share and enjoy:"

link|improve this answer
show 4 more comments
feedback

include function always via Hook, not directly.

Example:

  • Dont use for include the class of the plugin via new without hook

  • Use the Hook plugins_loaded

    // add the class to WP                                   
    function my_plugin_start() {                                                               
        new my_plugin();   
    }                                                        
    add_action( 'plugins_loaded', 'my_plugin_start' );
    

Update: a small live example: Plugin-svn-trunk-page and a pseudo example

//avoid direct calls to this file where wp core files not present
if (!function_exists ('add_action')) {
        header('Status: 403 Forbidden');
        header('HTTP/1.1 403 Forbidden');
        exit();
}

if ( !class_exists( 'plugin_class' ) ) {
    class plugin_class {

        function __construct() {
        }

    } // end class

    function plugin_start() {

        new plugin_class();
    }

    add_action( 'plugins_loaded', 'plugin_start' );
} // end class_exists

You can also load via mu_plugins_loaded on multisite-install, see the codex for action reference: http://codex.wordpress.org/Plugin_API/Action_Reference Also here do you see, how inlcude wP with this hook: http://adambrown.info/p/wp_hooks/hook/plugins_loaded?version=2.1&file=wp-settings.php I uses this very often and its not so hard and early, better as an hard new class();

link|improve this answer
1  
a small live example: [Plugin-svn-trunk-page]svn.wp-plugins.org/filter-rewrite-rules/trunk/… and a pseudo example //avoid direct calls to this file where wp core files not present if (!function_exists ('add_action')) { header('Status: 403 Forbidden'); header('HTTP/1.1 403 Forbidden'); exit(); } if ( !class_exists( 'plugin_class' ) ) { class plugin_class { function __construct() { } } // end class function plugin_start() { new plugin_class(); } add_action( 'plugins_loaded', 'plugin_start' ); } // end class_exists – bueltge Feb 14 '11 at 21:11
1  
@Netconstructor.co - i have update the thread, the comment ist ugly for code – bueltge Feb 14 '11 at 21:14
show 1 more comment
feedback

Test your plugin

We should definitively have some testing tools on our plugin development environment.

Based on this answer by Ethan Seifert to a testing question, these are good practices to follow:

  • Your Unit Testing should test the smallest amount of behavior that a class can perform.
  • When you get up to the level of functional testing this is where you can test you code with Wordpress dependencies.
  • Depending on what your plugin does -- consider using Selenium-based tests which test for the presence of data in the DOM by using IDs
link|improve this answer
1  
But covering the smallest first is basic, so that you can reach the functional testing with WordPress as the answer says, isn't that right? – Fernando Feb 17 '11 at 3:55
show 2 more comments
feedback

Care about future WordPress & theme versions

Note: After re-reading this advice, I now step back from this practice as checking every function for existence may slow down your site.

Check if functions are deprecated directly in your theme.

This is a "could be like that" example.

if ( ! function_exists( 'wp_some_fn' ) ) 
{
    $theme_data = get_theme_data( get_stylesheet_uri() );
    $error = new WP_Error( 'wp_some_fn', sprintf( __( 'The function %1$s is deprecated. Please inform the author', TEXTDOMAIN ), "Theme: {$theme_data['Name']}: Version {$theme_data['Version']}" );

    // abort
    if ( is_wp_error( $error ) )
        return print $error->get_error_message();
} 
// else if no error - the function works and exists
wp_some_fn();

For proper/best practice error handling see this answer: link

You could drop even the $cause into the function. This will help you and your users to keep on track with functions or classes in your theme that might change.

link|improve this answer
feedback

Use WordPress's Coding Standards

http://codex.wordpress.org/WordPress_Coding_Standards

You know how much easier it is to update code you've worked on vs. code someone else has put together? Coding standards make it easier for any developer working on a project to come in and see what's going on.

We know your plugin or theme is your own, and the way you break your lines and add your curly braces is an expression of your individuality. Every indent is a carefully thought-out statement. But with your custom code, you're contributing to WordPress, even if your code isn't in the core application. Coding standards help developers quickly get up-to-speed with your code.

link|improve this answer
feedback

Use uninstall, activate and deactivate hooks

There are three different hooks for this:

  • Uninstall register_uninstall_hook();
  • Deactivation register_deactivation_hook();
  • Activation register_activation_hook();

A detailed instruction with a working example can be found here..

link|improve this answer
feedback

Use some kind of templating mechanism

Many plugins tend to mingle code and html freely, which makes maintenance and debugging pretty hard. A better way is to put all your html in separate files and use something like this:

function parseTemplate($file, $options) {
    $template = file_get_contents($file);
    preg_match_all("!\{([^{]*)\}!", $template, $matches);

    $replacements = array();
    for ($i = 0; $i < count($matches[1]); $i++) {
        $key = $matches[1][$i];
        if (isset($options[$key])) {
            $val = $matches[0][$i];
            $template = str_replace($val, $options[$key], $template);
        }
    }

    return $template;
}

Then use it like this:

// In mytemplate.html
<h1>{title}</h1>
<h2>{date}</h2>
<p>{text}</p>

// In your functions.php
echo parseTemplate("mytemplate.html", array(
    "title" => $title,
    "date" => $date,
    "text" => $somethingelse
));
link|improve this answer
2  
-1 I think additional level of abstraction can do more harm than good. And where it does make sense (content that should be easily editable via form for example) it is better to use tools already available (like shortcodes) rather than add own templating functionality. – Rarst Jan 10 '11 at 7:46
show 2 more comments
feedback
1 2

Your Answer

 
or
required, but never shown

Not the answer you're looking for? Browse other questions tagged or ask your own question.