Properly Naming Plugin Actions and Filters

Sharing my thoughts on naming actions and filters, I make a (probably futile) attempt to get developers to create better, more extensible WordPress products. One the one hand hooks should be descriptive, and on the other hand they should be structured and consistent. Can these properties go hand in hand? It’s time for a standardised way of naming actions and filters in WordPress.

The WordPress plugin repository is open to pretty much all developers who wish to contribute to WordPress. In most cases, plugins in the plugin repository are not extensible — and in most cases, it doesn’t really matter. But when a plugin gets big enough (and good enough), users start to require more. They start to need minor adjustments to your plugin which aren’t necessarily useful for other users (otherwise, it could’ve just been changed in the plugin core). A prime example of such a plugin is Advanced Custom Fields: it’s focused on developers, has hundreds of thousands of users and offers a huge amount of functionality.

In such cases, offering your users a way to alter behaviour of the plugin is a step you have to take to be able to support your growth. In WordPress, this means taking the event-driven approach: offering action and filter hooks to developers.

Developers should be able to guess your action and filter names from their context and function. Consistency is key.

Writing a plugin in line with the event-driven approach WordPress core itself uses is quite a challenge. Where should you add actions and filters, and where shouldn’t you? Are there cases where you should hook into your own filters or actions from within the very plugin that calls them?

These are all very interesting questions. In this article, however, we’ll focus on naming actions and hooks. The WordPress Coding Standards provide no insight in this, and the list of WordPress core actions and filter hooks consists of probably thousands of inconsistently named hooks. Even new hooks added to WordPress have no real structure as far as naming is concerned. This is not necessarily a problem: the main aim of hook naming in WordPress is making them descriptive.

In my opinion, descriptive names are not the only requirement for custom actions and filters from plugins. Developers need to be able to rely on your plugin’s extensibility. They need structure and consistency.

Everyone will have their own approach on this, but as always, mine is beyond shadow of a doubt correct. So, how to name your actions and filters?

Prefixing

First and foremost: (consistent) prefixing. This is one of the most easily forgotten aspects of naming actions and filters (and functions and classes, and just about everything else, for that matter) in plugins. Prefixing hook names with an abbreviation, acronym or the full plugin name prevents duplicate action names and allows a user to instantly see to which plugin a filter belongs.

Anything you create in the global namespace has the potential to conflict with a theme, another plugin (including one you wrote), and WordPress core itself.
Andrew Nacin, 2010 (nacin.com)

I usually choose the full plugin name if it’s a single word, and the first letter of each word otherwise. In some cases, I prepend the prefix with a shorthand of my company name. For WooCommerce, for example, I would prefer the prefix woocommerce, for Advanced Custom Fields I would use acf, and for Gravity Forms I would consider both rggf (Rocket Genius is the developer of Gravity Forms) and gravityforms proper prefixes.

Be sure to prefix all of your action and filter names consistenly with this prefix (followed by a delimiter).

Structure: Context and Function

Next up is the actual filter structure. Rarely used by plugins, this is really the core of this article. In my opinion, action and filter names should be fully predictable based on the actual function of the hook and the context it appears in.

I believe that every single action and filter should consist of a prefix, followed by (in most cases) the context, followed by the name of the data being filtered (in case of filters) or an indication of what has just happened or is about to happen (in case of actions). Let me elaborate on this by posing an example.

Let’s say we have a plugin that handles payment requests, called “Easy Payment Requests” (prefix epr), with which we’re instantiating a request by creating a request object. For each request, we would like to be able to filter the currency. In my opinion, the only proper filter name would be epr/payment-request/currency, probably passing the request object: $currency = apply_filters( 'epr/payment-request/currency', $currency, $this );.

Context

As is clear from this example, the context I’ve chosen is “payment-request”, which is essentially the object name (probably EPR_PaymentRequest) with words separated by dashes. With a well-structured plugin, the context is always easily derivable, especially for class-driven plugins adhering to the single responsibility principle.

The context is generally either a data model, such as in the example above, or a particular “part” of your application. The latter includes cases such as “admin” and “settings”. As a rule of them, the context part of your action or filter name is the part of your application being referenced, which has a property being manipulated (for filters) or an action being performed inside that context (actions).

In most cases, the context would be a single name. In some cases, however, it might consist of two or more parts: consider a form field in Gravity Forms, for example, with a filterable title. The filter might look like this: gravityforms/form/field/title, where the context clearly consists of two tiers: form and field, the latter being a “child” of the former.

Function

Last up is the function of the action or filter hook. As I’ve stated before, this should be the action that has just happened or is about to happen for actions, and the property being filtered for filters.

Applying this to the payment request example, which is a filter, this would simply be currency: the currency is the property of the payment request being filtered.

As a simple guideline, the function part of an action should always express an actual action or point in time. In just about all cases, it should contain a verb. For example, if you want to supply a callback after completing a payment request (following the original example), a good action name would be epr/payment-request/after_processed.

Do as you may, but be consistent

In my ideal world, all plugin developers would adhere to this structure in actions and filters, which does leave some room for debate. However, the main message I want to convey is that, however you wish to name your hooks, whether you want to use slashes, underscores, dots or dashes, please choose a structure and stick to it. Make life easier for fellow developers: when extending your plugin, they should be able to guess the name of an action or filter from its function and context.

I would be happy to hear your thoughts and your standards for naming actions and filters! Just leave a comment below and I’ll get back to you!

Sharing is caring!

Leave a Reply

Your email address will not be published. Required fields are marked *