Where to add hooks in a class

Where to add hooks in a class?

“In class-based object-oriented programming, a constructor (abbreviation: ctor) is a special type of subroutine called to create an object. It prepares the new object for use, often accepting arguments that the constructor uses to set required member variables.” Source: Wikipedia.

The constructor is not the place to add actions and filters.

In the code below, shouldn’t the hooks under the bottom two functions be placed inside the constructor?

The above code is invalid and will throw an error when you try to run it. The hooks under the bottom two functions need to be placed in a method, but not necessarily the constructor.

There are many things that I would change with the above code.

Firstly, what is the one thing this class does? Impossible to answer since it does more than one thing. It add hooks, it enqueues styles and scripts, and it deactivates plugins. That suggests it should be broken up into more classes.

Secondly, I never use the singleton pattern. See here for why.

Thirdly, there’s no reason for the & before $this. That’s a holdover from PHP 4. All object in PHP (that WordPress supports) are now passed by reference so there’s no reason to do this. This won’t actually cause any side effects, it’s just a code smell.

functions.php

//* Start bootstrapping the plugin
require __DIR__ . '/bootstrap.php';
require __DIR__ . '/plugin.php';

//* Use the plugins_loaded at priority 0 to finish bootstrapping
$plugin = new plugin();
add_action( 'plugins_loaded', [ new bootstrap( $plugin ), 'plugins_loaded' ], 0 );

bootstrap.php

class bootstrap() {
  public $plugin;
  public function __constructor( $plugin ) {
    $this->plugin = $plugin;
  }
  public function plugins_loaded() {
    array_map( function( $hook ) {
      method_exists( $this->plugin, $hook ) && add_action( $hook, [ $this->plugin, $hook ] );
    }, [ 'plugins_loaded', 'after_setup_theme', 'init', 'admin_init', 'wp' ] );
  }
}

plugin.php

class plugin() {
  public function plugins_loaded() {
    //* Maybe you want to require more files here
    add_action( 'init', [ $this, 'public_init' ] );
  }
  public function plugins_loaded() {
    //* This method fires on plugins_loaded
  }
  //* WordPress doesn't fire a hook on public init
  public function public_init() {
    if( is_admin() ) return;
    //* Add some hooks for the public side
  }
  public function admin_init() {
    //* Add some hooks for the admin side
  }
  public function init() {
    //* Add some hooks for both public and admin side
  }
  //* Etc.
}

This is how I structure how to add hooks to plugins and themes. It’s not necessarily the best. It’s certainly not the only way.