I plan to put together a mini-series covering the basics of properly planning, engineering, launching and maintaining a WooCommerce shop. In the future as I write additional articles I will link them together, for now, this first article will cover the basics of creating a custom plugin for your WooCommerce site, and provide you with a plugin skeleton to download and use as a starting point. This article assumes a familiarity with basic WordPress plugin development, and expands upon the WooCommerce doc article on creating a plugin. So, let's get going!
Why a Custom Plugin?
WooCommerce is a fabulous ecommerce solution, but creating a website or shop is a very personal endeavor, and you are likely to want to change some functionality or behavior of the stock WooCommerce plugin. Our natural tendency is to look for simple solutions, and therefore we can be drawn to editing the core files. Resist this base urge! Repeat after me: “I will not modify the core files.” Fortunately, though not as flexible as Magento, WooCommerce provides a lot of action hooks, filters, template files, and “template functions” to allow for customizations. Writing a plugin allows us to cleanly separate and keep track of our custom code, and renders WooCommerce upgrades a relatively painless process.
What is an action?
An action in WordPress allows you to execute code triggered at a specific point in the page response process, for instance upon displaying a comment.
What is a filter?
Similar conceptually to an action, filters allow you to modify data at specific points in the WordPress page response process, for instance removing profanity from a comment.
What is a template?
A template is a file that contains a mix of HTML and PHP code and renders a page, a part of a page, or an email. Templates can be overridden by creating a file of the same name in a special location within your theme or child theme.
What is a template function?
A “template function” is a function that begins with if ( ! function_exists( 'function_name' ) {
… If your plugin defines this function first it will be called in place of the default function and allow you to override its behavior with your own.
Writing a custom plugin largely allows you to alter the functionality and behavior of WooCommerce; to customize the look and feel the preferred method is to create a custom child theme. I won’t cover that process in this article series as it is already described well in the WordPress codex and there isn’t much WooCommerce-specific to add. The exception is perhaps the way that you override WooCommerce template files, which I wrote about in another article.
The Plugin Skeleton
I prefer to name my WooCommerce custom plugin woocommerce-company-name, so if your company is Acme, inc, you might use woocommerce-acme. Although not strictly necessary with a self-authored plugin, it’s good practice to check if WooCommerce is active, and also perform a check to ensure a class with the same name as your plugin doesn’t already exist:
if ( in_array( 'woocommerce/woocommerce.php', apply_filters( 'active_plugins', get_option( 'active_plugins' ) ) ) ) {
if ( ! class_exists( 'WC_Acme' ) ) {
Next, it’s again good practice though not necessary, to load any translated strings for the plugin. Doing so allows you to use the various translate functions such as __( 'Some text', 'wc_acme' )
and easily provide translation files at some future date.
load_plugin_textdomain( 'wc_acme', false, dirname( plugin_basename( __FILE__ ) ) . '/' );
I prefer to define the bulk of my plugin functions within a class, which effectively scopes the functions you write and keeps you from having to worry about function name clashes with all the other WordPress core and plugin functions. There are a few commonly used lifecycle action hooks which will be included in our skeleton plugin class. Finally, the plugin class will be instantiated, assuming that WooCommerce is active, and the class name isn’t already taken.
class WC_Acme {
public function __construct() {
// called just before the woocommerce template functions are included
add_action( 'init', array( $this, 'include_template_functions' ), 20 );
// called only after woocommerce has finished loading
add_action( 'woocommerce_init', array( $this, 'woocommerce_loaded' ) );
// called after all plugins have loaded
add_action( 'plugins_loaded', array( $this, 'plugins_loaded' ) );
// indicates we are running the admin
if ( is_admin() ) {
// ...
}
// indicates we are being served over ssl
if ( is_ssl() ) {
// ...
}
// take care of anything else that needs to be done immediately upon plugin instantiation, here in the constructor
}
/**
* Override any of the template functions from woocommerce/woocommerce-template.php
* with our own template functions file
*/
public function include_template_functions() {
include( 'woocommerce-template.php' );
}
/**
* Take care of anything that needs woocommerce to be loaded.
* For instance, if you need access to the $woocommerce global
*/
public function woocommerce_loaded() {
// ...
}
/**
* Take care of anything that needs all plugins to be loaded
*/
public function plugins_loaded() {
// ...
}
}
// finally instantiate our plugin class and add it to the set of globals
$GLOBALS['wc_acme'] = new WC_Acme();
Wrapping Up
If you were already familiar with WordPress/WooCommerce development there probably wasn’t much new for you here, but hopefully if you’re new to the game then the above explanations and techniques will prove helpful in getting you started. Either way, the best way to learn the multitude of WooCommerce actions and filters available for customization is to browse the source code. Also remember that in addition to hooking into actions/filters and adding functionality, you can just as easily unhook existing actions/filters to remove plugin behavior, or change it wholesale.
The trick is to perform the remove_action()
/remove_filter()
calls after the target action is hooked to (for instance within our woocommerce_loaded()
function above), and to always remember to provide all the arguments to the remove functions that were passed in the add functions, optional parameters and all.