Plugin: Hooking up classes that have their own hooks

Was wondering if there is a “best” approach to hooking up classes that has their own hooks, still making sure that those hooks haven’t run before the class got a chance to declare it’s own said hooks.

I’m getting lost in the hook hierarchy in the context of an OOP plugin, and I’d rather not have all hooks in a single “god” constructor (as mentioned here: Best way to initiate a class in a WP plugin?)

I’m currently working on making plugins dependent on each other (seperation of concerns), and I’ve run into various issues in this regard; issues like classes not existing because they haven’t been initialized yet.

I’m sure there isn’t an easy answer to this, based on how WP is structured. Maybe the answer is simply to rethink and redesign the plugins from scratch.

Appreciate any insights experienced WP OOP plugin developers have.

Solutions Collecting From Web of "Plugin: Hooking up classes that have their own hooks"

Constructors should not do any any work, they are there for instantiation of your class. It is good that you are trying to build classes that are only concerned to doing one single thing (SOC). I think your issue is more of how to use these classes as a combined working system, because, if done corrctly, you should not have the issue you are having.

For me, WordPress classes are a true mess as they

  • do way to much work (the ‘god’ class that everyone talks about)

  • use public properties (always use protected or private properties, properties should not be available outside the class except another class which is used to extent the parent class)

The point of this is, you should not look at WordPress classes as inspiration.

Just to go off topic quickly, for SOC, look into interfase injection (more especially setter injection). @gmazzap has put interfase injection to a wonderful use in his answer here. There are also a huge amount of info regarding interfase injection on the net. You can also check out my question over at codereview regarding this issue.

To come back to your question, This is an example how I use hooks in a class (with added setters and getter for setter injection as examples). As I said, you constructors should not do any work, so move your actions and filters outside the constructor

class PropertyValue
{
    // Add my protected and/or private properties here
    protected $propery;

    // Constructor
    public function __construct( $property = NULL )
    {
        $this->property = $property;
    }

    // For setter interfase injection, define your setters and getters
    // Setter method
    public function setProperty( $property )
    {
        $this->property = $property;
        return $this;
    }

    // Getter method
    public function getProperty()
    {
        return $this->property;
    }

    // This will be the method used to run our hooks
    public function init()
    {
        add_action( 'wp_head', [$this, 'hookedMethod'], PHP_INT_MAX );
    }

    // This is the method we will hook to wp_head or any other hook for that matter
    public function hookedMethod()
    {
        // Use $this->property to do something with.
        $value = 'This property value is ' . $this->property;
        ?><pre><?php var_dump( $value ); ?></pre><?php
    }
}

You now are going to use this class as follow

$newclass = new PropertyValue;
// Set the value of the property through the setter injection
$newclass->setProperty( '$100 000' );
// Call the init() method of our class in order to execute our hook
$newclass->init();

You should now see This property value is $100 000 being dumped in your header

This is just very basic, and should answer your question at bare minimum. As I said, look at the linked posts on how to use setter interface injection and also make use of google for tons of examples and tutorials on this. Unfortuantely how everything will fit together would be off topic here as that will be generic PHP, so if you have any issues with interfaces, you should seek support on stackoverflow which is geared up to handle those specific issues 😉