One of the things that Pippin, Norcross, and I have been talking about during the course of building Comments Not Replied to is the best practices for instantiating WordPress Plugins.

Specifically, we’ve gone from simply creating an instance of the plugin, to storing it within the PHP $GLOBALS variable, as well and then debating whether or not to implement the plugin as a singleton.

Screen Shot 2013-02-19 at 10.27.46 AM

There’s more to this that I’ll cover in a follow-up post, but the most significant thing worth sharing in this post is why we’re discussing how to instantiate our plugin.

Wait, What’s Instantiation?

Generally speaking, I think programmers use a lot of big words to describe a simple concept, but I’ll cover that in a later article.

For those who aren’t aware, instantiation is basically the act of generating an actual instance of a class (instance, get it)? Whenever you do:

new Plugin_Name();

You’re instantiating a class. In typical representing, you end up storing a reference to the class in a variable:

$my_plugin = new Plugin_Name();

In this latter case, we do this for two reasons:

  1. We’re able to reference the functions and properties of the class.
  2. We’re able to de-construct, nullify the reference, release the resources (whatever you want to call it)

But you lose all of that ability in the the first example because the class is being created without being bound to a reference.

So What’s The Problem?

In a sense, you’ve created an orphaned object because you have no way to access it, or destroy it for that matter.

This can be problematic for a number of reasons:

  • You may wish to kill a reference to the object sometime during its lifetime in the context of another plugin or theme
  • You may wish to have access to its functions outside of the Plugin API to add, change, or modify its state
  • …and so on

So in order to do this, there’s a simple fix. Instantiate the object like this:

$GLOBALS['my-plugin'] = new Plugin_Name();

Here, we’re storing a reference to the plugin the PHP $GLOBALS collection that will allow us to access it at any place in the application.

Thanks to some of the comments below, I want to make it clear that there are two things that you need to be aware of when using this approach:

  1. Make sure that the key to which you’re assigning this instance doesn’t already exist.
  2. Understand exactly what you’re doing – if you’re unfamiliar with the $GLOBALS collection or why messing with it in a larger context can be dangerous, opt not to do it.

There are other strategies for storing the reference that will be covered in future posts.

Anyway, an example of how to, say, clear this particular reference would be to do something like this:

unset( $GLOBALS['my-plugin'] );

I’m not necessarily saying you should do this. It’s simply showing an example of how you can take advantage of maintaining a reference to the object.

There’s More Than One Way…

As with most things in programming, there are other ways to go about creating objects, maintaining references to them, and even managing how objects are related to one another.

Those are clearly the topics for other posts, but I hope to get to them soon.

Category:
Tips
Tags:

Join the conversation! 24 Comments

  1. Seriously: Don’t clutter the globals. Implement the plugin as a singleton instead. It’s much cleaner and really easy to do.

    • Yup – more on this (the Singleton, specifically) coming a bit later, but there are times where I think this is more acceptable than others.

      For example, if you’re building a utility for an intranet, small site, or something that won’t necessarily be used in conjunction with a variety of other plugins, utilities, or scripts.

  2. I tend to use the second in some cases, but have leaned toward the third case when using WP as more of an app platform and you need access to the class methods all over the codebase.

    • I’m currently working on a larger application that’s using WordPress as the foundation, so I need access to class methods all over the place.

      This has required a different approach that I hope to cover at some point in the future, but you’re absolutely right – when you need access to methods all over the code base, there needs to be a way to easily access them from some type of data (or object) store.

      I hope to eventually get to all of this stuff, too – even the simpler stuff, like Bjorn mentioned – at some point in the future.

  3. Thiago Senna Liked this post! But I never did this before just ’cause I saw every body just creating the object without putting them in a global variable. But also, I can’t blame them, just ’cause global variables are evil, in person.

    So I were you I’d put a really “red and bold” text saying “Danger! Just use the global object reference if you have sure about what you are doing!”

    Great post, Tom!

    • Thanks Thiago!

      I went ahead and actually updated the post as per this comment and Bjorn’s comment, as well.

      Too much to cover in a single post, but gotta start somewhere!

    • And well, about singletons… blame them, please! Singleton is so dangerous as global variables.

      • I don’t fully agree with this – there are definitely times when it’s appropriate to use them (especially when you truly want a single instance of an object).

        Additionally, in the context of a web application, a singleton may be exactly what you need so that the state of the object is maintained despite the number of page requests happening. Think not only about synchronous page loads, but even partials like with Ajax.

        Having a singleton can be really advantageous, it’s just they are often abused.

        • When correctly used, no problems about using singleton. But I’m sure that it’s easy to use singleton wrongly. In practice, singleton is a global variable. One thing is you, Tom, using Singleton in your project. Another thing is all new plugins on WordPress being done as Singleton. It’s too much space to make Singleton a anti-pattern like it’s already is in another languages like java, dot net, ruby, python and so on.

          Unfortunately I’m not expert enough to say how things should be done. But what I would try is to keep things stateless. In my opinion it’s easier to maintain, it’s easier to debug and I think that would scale better.

          Excuse-me for being so critic. :(

          • Ha – no worries at all, Thiago. As far as I’m concerned, it’s just a discussion on what we think is best and sharing information with one another. I didn’t take it as critical. I saw it just as your opinion.

            But you’re right: If every plugin in the repository is turned into a singleton, then it does become a bit of an anti-pattern. That’s why I think there are times to use it and times when to avoid it.

  4. I really like the following method but I never see it proposed in these discussions so it makes me wonder if I’m “doing it wrong”.

    Code copied from my RTE Comments plugin.

    /**
    * The main function responsible for returning the RTE_Comments instance
    * to functions everywhere.
    *
    * Use this function like you would a global variable, except without needing
    * to declare the global.
    *
    * Example:
    *
    * @access public
    * @since 1.0
    * @return mixed (object) || (bool) An instance of RTE_Comments or FALSE if the current user can not post HTML markup or JavaScript code in pages, posts, and comments.
    */
    function RTE_Comments() {
    return current_user_can( 'unfiltered_html' ) ? RTE_Comments::getInstance() : FALSE;
    }

    /**
    * Start the plugin.
    */
    add_action( 'plugins_loaded', 'RTE_Comments' );

    • I don’t know if this is necessarily doing it wrong. This is kind of like a remixed single pattern. Maybe some others will chime in, too, but FWIW, I don’t see this as doing it wrong.

      I’ll tweet this out as well and see if others will share their thoughts.

      • Thanks. It’s be interesting to hear any feedback. An important item I should have noted, I actually came across this method in another plugin, be darned if I remember which one. I should have put it in my doc block. But I really liked it so I’ve been using it since.

  5. Is the other way you speak of dependency injection, thus removing the use of GLOBALS and singletons?

    For example:

    $my_plugin = new Plugin_Name();
    $inject_my_plugin = new SomeClassUsingCode($my_plugin);

    It would be great to see some examples of how it can be used in WordPress as a pattern and also some Autoloading Classes.

    • That’s one of the ways and your timing is awesome – dependency injection is one of the topics that I wanted to cover next.

      Just wanted to lay the ground work with this post, first :).

      Good call.

      • There’s so much I want to comment about on this post, but only have the time today to say that the standard patterns for dependency injection add a lot of complexity to using classes, complexity that will likely overwhelm people whose primary job is not full time developers and I think the majority of WordPress professionals fit into that category.

        How we handle dependency injection is via register() functions that allow us to register the classes that are needed and associate with a simple name similar to how registering a post type works. Then let the user specify the name when they need an object instead of forcing them to deal with instantiating the object. Further if more flexibility is needed they can add a filter to filter the dependent object’s properties.

        It’s not the “standard” pattern for dependency injection and thus people familiar with the standard may not recognize it at first but the results are the same. We get simplicity of use without that downsides that come with not using dependency injection.

        • the standard patterns for dependency injection add a lot of complexity to using classes

          Agreed. In fact, one of the points that I’m eventually doing to make is that I think “dependency injection” is a dumb term. I think that it sounds far more complex than for the idea that it really represents.

          Anyone with a basic OOP background understands the idea, they’ve probably just never labeled it as such.

          How we handle dependency injection is via register() functions that allow us to register the classes that are needed and associate with a simple name similar to how registering a post type works.

          This actually sounds really neat. Whenever I get to the point of publishing the post on dependency injection, my thoughts on the technique as a whole, and the benefits of it (as well as when not to bother using it, even), hopefully you’ll have time to share a bit more.

          I’d dig seeing this thing in action (even if it’s just a link to a GitHub repository).

          • In fact, one of the points that I’m eventually going to make is that I think “dependency injection” is a dumb term.

            Absolutely, I could not agree more! I know what it is but every time I hear it I have to do contemplate it just like I do if someone writes in Spanish (I know a little bit of Spanish.) It would be so much better if the term used didn’t require mental translation.

            I’d dig seeing this thing in action (even if it’s just a link to a GitHub repository

            Thanks for the interest, and would love to show it. My GitHub repos each have a lot more complexity than this so there’s nothing simple enough to show as an example. And I’m pushing hard to finish some tools I plan to release soon, some of which will use these exact techniques, so I’ll be able to write about it soon but not today.

            P.S. The more I read your stuff the more it seems that as programmers we think alike. Nice to have a kindred spirit who is so prolific.

          • The more I read your stuff the more it seems that as programmers we think alike. Nice to have a kindred spirit who is so prolific.

            Thanks – I really appreciate that. I’d hardly consider myself prolific, but y background is in software engineering and I’ve got a passion for it.

            I’m slowly trying to bring that influence into WordPress because I see its potential as a platform, but I also see a lot of hobbyists and “just get it working” types shipping stuff.

            Though I dig the idea of getting something out the door, I think it’s important to make sure good practices are at least being followed for the sake of compatibility with other plugins and themes, but also to avoid technical debt, too.

            That’s probably discussion for a post in and of itself, though.

      • You are posting (almost) daily. That’s pretty prolific to me! :)

  6. If you want remove a filter/action on hook from plugin without global variable, try :
    https://github.com/herewithme/wp-filters-extras

Leave a Reply