If you look at any WordPress plugin of significant size, you’ll probably find most of them boot the same way. From BuddyPress, to PressForward, to JetPack, all of these boot the same way: with singletons. JetPack in particular is interesting, as many of its modules are also singletons themselves. It’s an extremely common pattern in WordPress plugin development, wrapping the main plugin class in a singleton and instantiating it through a static method, which then enforces only a single instance of the class exists and can ever exist. The prototypical example looks like this in PHP:
protected constructor: This means that the class can only be instantiated by itself (in this case, by the static
init method), so no other code can create a new instance of the class. That same
init method saves the . The second time, the instance already exists statically and is returned directly.
Singletons are generally an anti-pattern in wider object-oriented development. The biggest issue is if you ever find yourself needing two instances of the object, you’re screwed; it’ll take a ton of refactoring to undo all the locations in which the singleton static method is called.
Singletons are generally much worse in other languages, like Java, where the application is long-running and there is a shared memory space. The drawbacks often encountered in those languages are not encountered in PHP, with its stateless, single-thread, fire-and-die approach to web development.
Even though I’m a big fan of WordPress generally, it’s full of anti-patterns (omg the globals!), so I’m not really that bothered by the idea of plugin developers adding another one onto the heap, and in this case, it actually solves a lot more problems than it causes because in WordPress, you don’t want multiple instance of your main plugin class floating about. However, the singleton pattern does still have an issue in WordPress:
You’ve completely locked yourself off from your constructor.
This generally isn’t a huge issue in WordPress plugins, as most plugins don’t do any kind of unit testing, but if you’re interested in doing unit testing and your main plugin class has any dependencies at all, being unable to access your constructor means you’re unable to mock any of those dependencies, or pass in anything at all.
I’ve spent a little bit of time playing around with Laravel, Pimple, and some of the other dependency injection containers out in the wider PHP world, because I wanted to more effectively unit test my plugins, and in addition to the singleton pattern, many of those main singleton classes also function effectively as containers as well. PressForward sets up all its dependencies there and uses them throughout the application, so I wanted to build something that fits with the pattern many WordPress plugin developers are already familiar with. That means the main application container class should be a singleton.
Instead of through static methods, you can enforce the class’s singleton-ness the class’s constructor:
Now, if an instance already exists, an Exception is thrown, so another developer would not be able to instantiate a new instance of the main plugin class. The constructor its is now exposed, so any dependencies, even if it’s just the boot file location, can be passed into the main class, and the class’s singleton-ness is still maintained.
Now, you might think you just throw
$app = new PluginClass(__FILE__); into your main plugin file and you’re good to go, but you’d be wrong. We’re doing all this work to minimize the number of global variables, so that would be a bad idea. You could wrap it in a function so no global variables are leaked, but then you’ve added a global function (less of a problem, but still a problem). So there’s one more trick I’d like to share:
This was pulled from a suggestion in a pull request on the WordPress Plugin Boilerplate, so I can’t claim credit for it, but it is a great way of solving the global problem. Now, the class is instantiated, its boot method is run, access to its constructor is preserved, no globals are leaked, and you still enforce it as a singleton.
This singleton design is implemented in the WordPress plugin framework I’m building, jaxion, so you can see the current implementation here. The boot method will be the default startup for jaxion-boostrap, the plugin boilerplate built on jaxion. You can see the current implementation here.
What do you think? Will you start using this singleton pattern in your WordPress plugins?
This post is part of the thread: Project: wppb-mod - an ongoing story on this site. View the thread timeline for more context on this post.
Trump is not a troll but exactly the result we should expect from our political and media systems:
Trump is called a troll because he’s said to not be a real candidate running a real campaign, that he’s not playing by the standard rules and not engaging in politics and democracy in good faith. But this is what makes Trump like the rest of the candidates and campaigns. That Trump is gaming the election coverage isn’t some kind of unsolvable problem but what such coverage asks for. As the Diana Christensen character says in the film Network (1976), “If you’re going to hustle, at least do it right.” The “Trump problem” for journalists is solved the moment we stop presupposing that the rest of the candidates and news coverage is real and in good faith.
Keep screwing up like this, WordPress, and you won’t own 24% of the web for long.
At a time when the Republicans are beclowning themselves, liberal Democrats need only to remain cohesive and even-keeled while the right hangs itself politically. But when it appears as if even the most liberal of the Democratic candidates are out of touch with African-American activists, and when it appears as if the progressive base is caught in the throes of in-fighting, it exposes political weaknesses to be exploited.
Just a regular reminder that you do not own your social media account, you rent it.
The leaps of logic required to speak this statement with even an ounce of seriousness is actually kind of impressive.
“I couldn’t help but think of Galileo,” he said, producing some halting chuckles. Galileo was a Catholic, Taylor explained, and he “wasn’t defiant to the Church.” Galileo merely understood that it would be better for the Catholic Church to be right about the scientific question of the nature of the Solar System. “Thank goodness for Albert Einstein. Thank goodness he was a denier,” Taylor said. “Thank goodness Sir Isaac Newton was a denier. Thank goodness that Galileo was a denier.”
As a sociologist who has read critical race theory and learned from critical race theorists, Robinson’s tweets, for me, were impassioned statements of well-established and well-founded lines of thought. For the uninitiated, however, they were jarring. The average nice white ladies of the world don’t understand that “whiteness is most certainly and inevitably terror” refers to a history of white-on-black interpersonal and institutional violence, degrading media portrayals, over-policing and under-protection of black communities, hypersexualization of black women, and fear mongering aimed at black men. And of course they don’t, that’s one of the key points of critical race theory: cultural logics render power-hierarchies invisible while perpetuating race-based opportunity structures that privilege whites.
Handy chart to check if you should work for free. tl;dr: Mostly no, unless it’s your mom.
lol @ Oracle claiming copyrighting APIs is good for innovation. This can only end poorly.