Today, I ran into code like this.
<?php class Badly_Designed_Plugin { public function __construct() { add_action( 'woocommerce_after_my_account', array( $this, 'display_something_useless' ) ); } public function display_something_useless() { echo "I am a very badly designed plugin!"; echo "I will make people sad."; } } new Badly_Designed_Plugin();
So what’s the problem here?
There is no way to remove display_something_useless() function from ‘woocommerce_after_my_account‘ action.*
Normally, I would do this:
remove_action( 'woocommerce_after_my_account', [$instance_of_badly_designed_plugin, 'display_something_useless'] );
However, there is no way for me to access the instance of Badly_Designed_Plugin class. By doing:
new Badly_Designed_Plugin();
..it’s created and just left to hang around in the void with no a reference to it. Don’t do this.
Instead, if your class is supposed to have a single instance of it ever, just use a Singleton.
Example:
<?php class Nicely_Designed_Plugin { private static $instance; public static function get_instance() { if (null === static::$instance) { static::$instance = new static(); } return static::$instance; } protected function __construct() { add_action( 'woocommerce_after_my_account', array( $this, 'display_something_useless' ) ); } public function display_something_useless() { echo "I am a very nicely designed plugin."; echo "If someone wants to customize me, they can do it!"; } } Nicely_Designed_Plugin::get_instance();
Now, calling Nicely_Designed_Plugin::get_instance() will always return the same instance of Nicely_Designed_Plugin – the instance that’s tied to that WooCommerce action.
So in order to get rid of that useless action, I can do this:
$instance_of_badly_designed_plugin = Nicely_Designed_Plugin::get_instance(); remove_action( 'woocommerce_after_my_account', [$instance_of_badly_designed_plugin, 'display_something_useless'] );
And no, singletons are not inherently evil. They are evil if used in the wrong context. A small WordPress plugin is a perfectly okay place to use a Singleton.
* Actually, there is a way, though it’s pretty bad if you have to use it. See here and here.