Namespacing WordPress Plugins
Why namespaces? There are thousands of plugins out there and chances are rising that someone writes a class or function with the same name as you do. Once a user activates both plugins, PHP doesn’t know which function to use and exits peacefully. Use namespaces to prevent this from happening.
There are four ways to namespace WordPress plugins.
- You don’t care — which is never a good idea. But you do because you’re reading this post. Awesome!
- Prepending all your function names with prefixes
- Use a class as a namespace and nest all your functions in that class
- Use the PHP 5.3 language feature “namespace”
Prefixing
Prefixing is the quick and dirty approach. Your plugin is called The Troublesome But Cool Widget, so your prefix might be ttbcw. Every function you write starts with that prefix, so instead of init, your function will be named ttbcw_init.
It’s an acceptable solution for small plugins where you don’t have to write more than a handful of functions. However, it’s quite ugly and becomes increasingly unhandy the more complex your plugin grows.
Class as Namespace
That’s what you’ll find quite often if you look into popular plugins today. Many developers avoid real namespaces as they require PHP 5.3, which is still not widely adopted by hosters. Have a look at the following example.
<?phpclass TheTroublesomeButCoolWidget { public function __construct() { $this->register_scripts(); $this->register_shortcode(); $this->register_setup_hooks(); } private function register_scripts() { /* ... */ } private function register_shortcode() { /* ... */ } private function register_setup_hooks() { /* ... */ }}
new TheTroublesomeButCoolWidget();Now you can reuse function names in all of your plugins — nice! By the way, it is advisable to implement the singleton pattern to avoid the possibility of initializing more than one instance of that class by accident. But that is outside the scope of this article. I’ll put a reference link into the resources section though.
Unfortunaltely, there is one major caveat: Splitting the plugin among multiple files is hard. Namespacing via classes encourages implementing all functionality in a single class and before you know your file has grown to a four digit number of lines of code. Let alone separation of concerns.
All in all, it’s an okay-ish solution for medium sized plugins — but still ugly from a software architecture perspective.
Real Namespaces
Recently, I have been talking about PHP 5.3 language features a lot. There’s always the question whether to use them or not. If you’re inclined to read more about it I can point you to some articles. Have a look at the comment sections, too!
Now, let’s assume we have agreed upon using 5.3 is not evil. At this point — let’s be honest — there’s no reason to use one of the solutions explained above. Native PHP namespaces are superior to all of them.
namespace TheTroublesomeButCoolWidget;
Simple, yet effective. You can declare any function names you like within this file. Nice bonus compared to class namespacing: Less indentation All functions may start at the beginning of the line.
Furthermore, you can start to divide your code into logical groups by nesting namespaces.
<?phpnamespace TheTroublesomeButCoolWidget;/* basic stuff */namespace TheTroublesomeButCoolWidget\Settings;/* code for the settings page */namespace TheTroublesomeButCoolWidget\Lib;/* utility functions */And so on. You start by developing in a single file and can refactor out chunks of code once they grow large easily. Developer heaven :)
Summary
If you have decided to go for PHP 5.3, use real namespaces. Now. There is no reason not to.
Otherwise choose between prefixing and class namespacing. I recommend to only use prefixing for very simple plugins. Class namespacing is an acceptable choice for medium to complex plugins but you have to be creative when it comes to distributing code among multiple files.
Resources
4 Responses to “Namespacing WordPress Plugins”
Leave a Reply
The problem with doing what you’ve described and not using a singleton is that it is pretty much impossible for other plugins to remove the hooks that you’ve added.
My solution to this has been to use all static methods for classes that shouldn’t have multiple “instances”. My approach is to give the class a start() method for setting up things like actions and filters.
With static methods, you can do something like:
remove_hook( 'hook_name', array( 'Class_Name', 'function_name' ) );
With non-static methods, you have to do something like:
remove_hook( 'hook_name', array( $class_instance, 'function_name' ) );
If you haven’t stored the instance of that class in a variable (which isn’t done in your example), it’s impossible to unhook that function programmatically.
One fix is to do the following when you construct the class:
global $my_class;
$my_class = new My_Class();
But I still think using static methods is better than this, because that way you don’t have to clutter up the global namespace with instance variables.
On another note, breaking your plugin up into multiple classes is definitely possible when you use classes. Simply partition your classes based on what they do, so if you have options that you need to manage, use a My_Plugin_Options class (and include it from the main plugin file). This way you can keep your plugin files manageable without having to define tons of global functions.
-
@Will Anderson:
At first: No other plugin should ever remove the actions and filters that my plugins added. Never ever.
The reason why i’m adding action & filters is, because without this actions & filters my plugin won’t work propperly.Second. There are more than one way to remove actions & filters. The roughest is to unset the array-elements from $wp_filter.
But removing a action/filter added with a namespace is very easy: remove_filter( $tag, ‘namespace\function’ );At least. There is no function “remove_hook”. Even Peter Pan have no function “Remove Hook” ;)
remove_action() is just a wrapper for remove_filter(). So there is only remove_filter()I think you commented on the wrong post. In WordPress you create “unremovable actions/filters” with anonymous functions, because remove_action/remove_filter needs a function-name to remove the action/filter.
But there is still the way with $wp_filter. It’s not easy, but it’s even not impossible ;)
Why would you only be restricted to a single class in a single file? You can use your first class to import and instantiate as many classes as you need.
The problem with doing what you’ve described and not using a singleton is that it is pretty much impossible for other plugins to remove the hooks that you’ve added.
My solution to this has been to use all static methods for classes that shouldn’t have multiple “instances”. My approach is to give the class a start() method for setting up things like actions and filters.
With static methods, you can do something like:
remove_hook( 'hook_name', array( 'Class_Name', 'function_name' ) );With non-static methods, you have to do something like:
remove_hook( 'hook_name', array( $class_instance, 'function_name' ) );If you haven’t stored the instance of that class in a variable (which isn’t done in your example), it’s impossible to unhook that function programmatically.
One fix is to do the following when you construct the class:
global $my_class;$my_class = new My_Class();
But I still think using static methods is better than this, because that way you don’t have to clutter up the global namespace with instance variables.
On another note, breaking your plugin up into multiple classes is definitely possible when you use classes. Simply partition your classes based on what they do, so if you have options that you need to manage, use a My_Plugin_Options class (and include it from the main plugin file). This way you can keep your plugin files manageable without having to define tons of global functions.
@Will Anderson:
At first: No other plugin should ever remove the actions and filters that my plugins added. Never ever.
The reason why i’m adding action & filters is, because without this actions & filters my plugin won’t work propperly.
Second. There are more than one way to remove actions & filters. The roughest is to unset the array-elements from $wp_filter.
But removing a action/filter added with a namespace is very easy: remove_filter( $tag, ‘namespace\function’ );
At least. There is no function “remove_hook”. Even Peter Pan have no function “Remove Hook” ;)
remove_action() is just a wrapper for remove_filter(). So there is only remove_filter()
I think you commented on the wrong post. In WordPress you create “unremovable actions/filters” with anonymous functions, because remove_action/remove_filter needs a function-name to remove the action/filter.
But there is still the way with $wp_filter. It’s not easy, but it’s even not impossible ;)
Why would you only be restricted to a single class in a single file? You can use your first class to import and instantiate as many classes as you need.
You’re right. That is possible. But it’s still misuse of the class syntax as a namespace.
There are definitely cases where classes are useful, especially when your plugin grows more complex. But from my perspective they should come in as an addition to namespaces and not the other way round.