Skip to content

Managing hooks

Hooks are a key part of WordPress that make it flexible and extendable. However, managing hooks in large and complex plugins can be tricky and prone to errors. One of the common issues is improper nesting of hooks, which can cause some hooks to never run due to their initialization timing.

For example:

add_action('init', 'initialize');
function initialize(): void
{
add_action('after_setup_theme', 'hello_world');
}
function hello_world(): void
{
echo 'Hello World';
}

In this example, the after_setup_theme hook might not run because it executes before the init hook. This shows why the timing of hook initialization is so important. In severe cases, you might see errors like maximum function nesting level reached.

To help minimizing these issues, this library includes the Hook object from the syntatis/wp-hook library. Inspired from similar object in WordPress Plugin Boilerplate, named Loader, the Hook object also provides a clear and organized way to define hooks and their callbacks, helping you avoid these common pitfalls.

Usage

When creating a new class within the app directory to add a new feature, you can implements the WithHook interface and provide the hooks you want to register in the hook method. Hereโ€™s an example of how you can use the Hook object to register a custom post type:

src/Portfolio.php
namespace WPStarterPlugin\PostTypes;
use WPStarterPlugin\Vendor\Syntatis\WPHook\Hook;
use WPStarterPlugin\Vendor\Syntatis\WPHook\Contract\WithHook;
class Portfolio extends WithHook
{
public function hook(Hook $hook): void
{
$hook->addAction('init', [$this, 'registerPostType']);
}
public function registerPostType(): void
{
// Register custom post type.
// See: https://developer.wp.org/reference/functions/register_post_type/
}
}

Then, you can instantiate it in the Plugin class within the getInstances method, like this:

src/Plugin.php
namespace WPStarterPlugin;
use WPStarterPlugin\PostTypes\Portfolio;
use WPStarterPlugin\Vendor\Syntatis\WPHook\Contract\WithHook;
use WPStarterPlugin\Vendor\Syntatis\WPHook\Hook;
/**
* The Plugin.
*
* Serves as the main entry point for the plugin, handling the initialization
* of core functionalities such as settings, blocks, and hooks, and
* managing activation, deactivation, and update processes.
*/
class Plugin implements WithHook
{
/**
* Initialize the plugin's features and components.
*
* @return iterable<WithHook|object>
*/
private function getInstances(): iterable
{
yield new Portfolio();
yield new Blocks();
yield new Settings();
}
}

Since the Portfolio class implementing WithHook interface, the Plugin class will also call the hook method as well as pass in the Hook object, and register the hooks thatโ€™ve been added in the Hook object.

This way, you can manage hooks in a more organized and structured manner without worrying about the timing of hook initialization, and avoid common issues that come with it.

Further reading

This chapter covers concepts such as the PHP interface, and yield and iterable keywords. If youโ€™re new to these and not yet familiar with these concepts, you can learn more about them from the following resources: