One of the advantages of working with object-oriented programming is the ability to define interfaces so classes that implement those interfaces have a strict set of functions that said classes must implement.

WordPress Plugin Interfaces

That is the definition of a class interface, anyway:

An interface is a contract specifying a set of methods, fields and properties which will be available on any implementing object

But how might this look if we’re aiming to create a namespaced solution for including WordPress plugin interfaces (or an interface) for a class that can be used to enqueue stylesheets or JavaScript files?

WordPress Plugin Interfaces: Assets

For the purposes of this post, assume that we’re defining an interface that will be used in the administration area of WordPress. That is, we’ll be creating an interface that will be used to enqueue stylesheets and JavaScript files.

We’ll need to incorporate the following:

  • a namespace that can be used throughout the project,
  • a function for initializing the class,
  • a function for actually enqueuing the assets.

And since this is generic enough that it can be used for JavaScript and stylesheets, I’ve opted to simply call it Asset.

The end result may look something like this:

Next, we need to actually implement the interface with a class. It should be relatively straightforward since we’ve set the methods that must be implemented.

Notice, however, that I provide a couple of properties that are set in the constructor of the class. These are specific to this class and make the act of actually enqueuing a file a bit easier.

A few things to note about the code above:

  • it uses the use keyword so that PHP knows we’ll be working with the Asset interface,
  • I’ve prefixed the name with JavaScript so it’s clear what type of asset I’m working with.

Finally, to instantiate the class that implements the interface, you simply do this:

Sure, this particular example is simple and I’ve left the usual code comments out but that’s generally for the sake of readability. If you want to see something like this in action, then review the source code for

If you want to see something like this in action, then review the source code for this particular plugin.

Category:
Articles
Tags:

Join the conversation! 6 Comments

  1. Hey Tom.

    Your posts are of excellent quality as always. Keep it up :)

    I have a minor question though regarding your OO implementations in the last few posts.

    Why not pass the initialization action or filter or whatever in the class constructor?

    Wouldn’t it be “cleaner” when we call the class?

    $assets = new Admin\JavaScript_Assets();

    instead of

    $assets = new Admin\JavaScript_Assets();

    $assets->init();

    After all since classes nowdays tend to follow a single responsibility principle.

    Unless there are other reasons/advantages of doing it that way, that my simple mind cannot think of.

    • Your posts are of excellent quality as always. Keep it up :)

      Thank you! I’m trying :)

      Why not pass the initialization action or filter or whatever in the class constructor?

      Because a class should be able to operate independently of WordPress. If you have your hooks defined in the constructor, then you’re creating tightly coupled classes to WordPress and that’s not a good thing.

      Having it de-coupled allows for improved testing and allows you to test each class without having to use WordPress to do so.

      Wouldn’t it be “cleaner” when we call the class?

      No, I don’t think it’d be cleaner. A constructor should initialize the properties that it maintains rather than making itself dependent on as few things as possible.

      In other words, less code is not always cleaner code.

      After all since classes nowdays tend to follow a single responsibility principle.

      This is a misunderstanding of the SRP. You can still have a single responsibility but require multiple method calls.

  2. @Tom, I agree with @Panos in the sense that a constructor might be a better option. How do you solve the tight coupling from hooks? The answer relies in polymorphism. You can have three classes: JavaScript_Assets, WordPress_Javascript_Assets and NonWordpress_Javascript_Assets. The first class is the parent that implements the functionality that child classes will share and then WordPress_Javacript_Assets can call WordPress specific hooks in the constructor.

    Finally you instantiate the object using a static factory method from the parent class. If you’re using WordPress, you’ll get a WordPress_Javascript_Assets object and you’ll get a NonWordpress_Javascript_Assets object otherwise.

    I have come across this problem and this is the most elegant solution.

    • @Tom, I agree with @Panos in the sense that a constructor might be a better option. How do you solve the tight coupling from hooks?

      Though I’ve stated the reasons I’m not a fan of it (testing and running classes in isolation being one of them), there are a variety of ways to do it.

      One way would be to use a registry class specifically responsible for binding a class’ methods to the proper hook. You can do this via dependency injection as needed.

      Polymorphism isn’t needed (and I don’t think it really comes into play right now). Assuming that polymorphism is being used as:

      the provision of a single interface to entities of different types.

      This is more apt to be used in situations whenever you have a generic type with a certain set of methods and properties that need a concrete type during runtime.

      This isn’t necessarily the case when you’re working with hooks.

      The first class is the parent that implements the functionality that child classes will share and then WordPress_Javacript_Assets can call WordPress specific hooks in the constructor.

      First, JavaScript_Asset works when you’re working with a pure JavaScript assets in the context of WordPress. NonWordpress_Javascript_Assets doesn’t really have a place in a WordPress-based project because it’s assumed that that is where it’s going to run.

      In this case, you’re better suited to a mock objects. So if that’s what you’re after, then perhaps there could be an interface for something like IMockable or AssetMock or something like that.

      Then when you need to test it, you instantiate Mock_JavaScript_Asset and that will separate it from it’s intended use.

  3. I think there seems to be a bit of confusion about some of the concepts here especially coupling.[1] Coupling is a structural problem in your code. It’s about how much a piece of code depends on another piece of code. It’s not limited to object-oriented programming either. (It appears in procedural code like WordPress core.)

    Polymorphism is an object-oriented feature.[2] By itself, it doesn’t reduce or increase coupling. Instead, its purpose is to increase code reuse between different classes by tying them together conceptually.

    Now, the goal of the single responsibility principle[3] is to help reduce coupling in your code. It does that by forcing you to design classes that have a specific job. The more specific the job, the better.

    This means that, in an ideal world, the whole process of registering hooks would be a job in itself.[4] But that’s not always realistic.[5] So we have each class manage their own hooks.

    That said, this doesn’t mean that registering hooks belong in the constructor. This creates unnecessary coupling between your class constructor and WordPress. A constructor is about creating an initial state for your object.

    Registering hooks isn’t part of that state. It’s a task that your class can handle after you’re done initializing it. That’s why it’s better to extract it and put it in another function.

    [1] https://carlalexander.ca/coupling-cohesion-wordpress/

    [2] https://carlalexander.ca/polymorphism-wordpress-abstract-classes/

    [3] https://carlalexander.ca/single-responsibility-principle-wordpress/

    [4] https://carlalexander.ca/design-system-wordpress-event-management/

    [5] https://carlalexander.ca/designing-class-wordpress-hooks/

Leave a Reply

This site uses Akismet to reduce spam. Learn how your comment data is processed.