In our last post "Enabling Action and Filter Hook Removal from Class-based WordPress Plugins" we offered the following as a suggested template for coding WordPress plugins:

  1. <?php
  2. /*
  3.  * Plugin Name: Your Plugin Name
  4.  */
  5. class Your_Plugin_Classname {
  6.   private static $_this;
  7.   function __construct() {
  8.     self::$_this = $this;
  9.     // Your constructor code goes here
  10.   }
  11.   static function this() {
  12.     return self::$_this;
  13.   }
  14.   // Your plugin methods go here
  15. }
  16. new Your_Plugin_Classname();
  17. [/code]
  18.  
  19. <p>Unfortunately there is an issue with this approach which we will fix in this post. </p>
  20.  
  21. <h2>A <em>De facto</em> Singleton</h2>
  22.  
  23. <p>The structure proposed is a de facto <a href="http://en.wikipedia.org/wiki/Singleton_pattern">Singleton</a> where Singletons are defined by Wikipedia to be:</p>
  24.  
  25. <blockquote>
  26. <p>A design pattern in software engineering that restricts the instantiation of a class to one object.</p>
  27. </blockquote>
  28.  
  29. <p>In our template the issue lies in the <a href="http://en.wikipedia.org/wiki/De_facto_standard"><em>de facto</em></a> part. Our class template is designed for only one instance but does not stop a developer from using <code>new</code> to create additional instances of the class. A second instance would overwrite the first in <code>self::$_this</code> which would create havoc for any code that expects <code>self::$_this</code> to be the same for the life of the <em>"page load"</em>[^page-load].</p>
  30.  
  31. <h2>Disallowing a Second Instantiation</h2>
  32.  
  33. <p>It&#39;s really quite simple; since a class&#39; <code>__construct()</code> method gets invoked whenever the <code>new</code> operator is used we need to test the <code>static</code> variable <code>self::$_this</code> to see if it has been set and if so call <code>wp_die()</code>. Note we used five lines below when we could have consolidated down to two but we wanted to ensure the code didn&#39;t wrap in this post:</p>
  34.  
  35. [code lang="php"]if ( isset( self::$_this ) ) {
  36.   $msg = &#39;%s is a singleton class and you cannot create a second instance.&#39;;
  37.  $msg = __( $msg, &#39;your-plugin-translation-domain&#39; );
  38.  wp_die( sprintf( $msg, get_class( $this ) ) );
  39. }
<?php
/*
 * Plugin Name: Your Plugin Name
 */
class Your_Plugin_Classname {
  private static $_this;
  function __construct() {
    self::$_this = $this;
    // Your constructor code goes here
  }
  static function this() {
    return self::$_this;
  }
  // Your plugin methods go here
}
new Your_Plugin_Classname();
[/code]

<p>Unfortunately there is an issue with this approach which we will fix in this post. </p>

<h2>A <em>De facto</em> Singleton</h2>

<p>The structure proposed is a de facto <a href="http://en.wikipedia.org/wiki/Singleton_pattern">Singleton</a> where Singletons are defined by Wikipedia to be:</p>

<blockquote>
<p>A design pattern in software engineering that restricts the instantiation of a class to one object.</p>
</blockquote>

<p>In our template the issue lies in the <a href="http://en.wikipedia.org/wiki/De_facto_standard"><em>de facto</em></a> part. Our class template is designed for only one instance but does not stop a developer from using <code>new</code> to create additional instances of the class. A second instance would overwrite the first in <code>self::$_this</code> which would create havoc for any code that expects <code>self::$_this</code> to be the same for the life of the <em>"page load"</em>[^page-load].</p>

<h2>Disallowing a Second Instantiation</h2>

<p>It&#39;s really quite simple; since a class&#39; <code>__construct()</code> method gets invoked whenever the <code>new</code> operator is used we need to test the <code>static</code> variable <code>self::$_this</code> to see if it has been set and if so call <code>wp_die()</code>. Note we used five lines below when we could have consolidated down to two but we wanted to ensure the code didn&#39;t wrap in this post:</p>

[code lang="php"]if ( isset( self::$_this ) ) {
  $msg = &#39;%s is a singleton class and you cannot create a second instance.&#39;;
  $msg = __( $msg, &#39;your-plugin-translation-domain&#39; );
  wp_die( sprintf( $msg, get_class( $this ) ) );
}

The Real Singleton

Adding the code snippet above to our template completes our singleton:

A Complete Working Example

Grabbing our code from our last post and adding the singleton logic gives us this example; to test just drop[^install-plugin] into your plugins directory:

Summary

When using classes as code wrappers for WordPress plugins as we've been recommending you are effectively using a Singleton without enforcing the singleton constraint. To disallow multiple instantiation use the isset( self::$_this ) test. If you don't then site builders, theme coders and other plugin developers might misuse your class by instantiating it a second time and overwrite your singleton instance. And nobody wants that. 🙂

Update

Be sure to read our follow up to this post where we talk about ensuring that classes uses for Singletons actually are limited to a single instance.

Related Links

Recently Eric Mann has had a field day writing about Singletons for WordPress, three (3) posts in little over a week (or should that be a "field week?") You'll note Eric recommends a slight different structure for singletons than we do. We'll address that in our next post:

About a year ago RJ Zaworski wrote a post offering his take on a:

RJ has some interesting techniques that were very clearly influences by Model-view-controller frameworks, approaches that are not common in the WordPress world. Nonetheless, his coding techniques are interesting.

[footnotes]
[^page-load]: When we refer to a "page load" we mean the entire lifecycle generated by an HTTP request where the PHP starting with /index.php is executed on the server and the resultant HTML is returned to the HTTP client which is typically a site visitor's browser.
[^install-plugin]: To test our example simply save as a file you can name thanks-for-reading.php in the WordPress plugins directory on your web server, typically /wp-content/plugins/ from the root of your website and then activate it like you would any other plugin.
[/footnotes]

4 thoughts on “Using Singleton Classes for WordPress Plugins

    • Hi @Chris,

      Thanks for commenting. Can you elaborate on what you mean by “multiple unique instances of your plugin on a page?” Are you referring to widgets, or something else?

      Reply

Leave a reply to Chris Howard Cancel reply

<a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code lang=""> <del datetime=""> <em> <i> <q cite=""> <s> <strike> <strong> <pre lang="" extra=""> 

required