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.
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:
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.
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>'; }
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__)), '/')
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? }
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:
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!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;
Depending on the scope of your plugin, you should consider adding your own custom hooks for future developers to extend your plugin.
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!
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 ) */