Archive for October, 2010

Explaining Hooks

Posted by igorw in Development with the tags , , , on October 9th, 2010

Most of you have probably already seen the blog post regarding the RFC process for hook locations to be added to Ascraeus (phpBB 3.1). And many of you may not know what a hook system actually is, so I will take the time to explain it.

In Olympus (phpBB 3.0) all new additions to the core must be made by editing or patching the core files. The MODification is either installed manually or by using AutoMOD. What a MOD usually does is add some specific code at a specific location, this ranges from database queries, template assignments and loading of language files to any custom PHP code. Now, this approach worked for 2.0 and it works for 3.0, but frankly it produces a horrible mess. Installing MODifications is a great pain, uninstalling them is almost impossible in many cases.

To solve this issue we are introducing a hook system. The hook system defines code injection points, giving each one of them a unique identifier. The hooks controller allows MODifications to bind to a specific code injection point or hook location. When that point is reached in execution, the hooks controller will call all of the hooks that registered, passing in the context, so that local variables can be read and/or modified by the hook, thus “injecting” the hook into that location. Technical details can be found within the General Hook Architecture RFC.


To remove the need for any core edits the files defining and registering hooks will be automatically loaded. They will be in a certain folder that phpBB will scan regularly. This will hopefully make the whole MOD installation procedure automagic. You drop in the files and are ready to go.

To make the registering of hooks more convenient, MOD authors will be able to define a class of which each method represents a hook.

This allows all hooks belonging to a certain MOD to be grouped within one file that can be automatically loaded and registered.


Here is an example with code. Note that this API may change since it’s not final yet. The hook location will be in user_add as described in this RFC topic ([RFC] user_add hook).

We will create a file called hook/logging.php (convention will change) containing the following class, which will be loaded automatically by phpBB.

Code: Select all
class phpbb_mod_logging
public function user_add(&$sql_ary, &$cp_data)
file_put_contents('registered_users.txt', time() . ": " . $sql_ary['username'] . "\n", FILE_APPEND);

Since we want to hook into user_add and the RFC describes the input arguments as $sql_ary, $cp_data (by reference), our hook will have to take those arguments. In this example we will write the unix timestamp and the username of every new user into a log file. This happens right before a user is created.

The user_add() function will execute all ‘user_add’ hooks before inserting the user. While we are only reading the arguments here, it is also possible for hooks to modify them.

Under the hood

So, how does this work? Let’s take a look at the engines that power this. These are mostly internals of the hook system that you will not have to deal with, because it is all taken care of by phpBB.

Before we can do anything hook related, we need to create a hooks controller. The hooks controller manages the hooks and makes sure all of them are called. All hook-related actions go through this class.

Code: Select all
// create the hooks manager
$hook_handler = new phpbb_hooks_controller();

In phpBB this controller is automatically loaded, and there is also code that will load all the hook files (hook/*.php). It registers the hook containers of those files with the hooks controller.

Moving on to the actual hook invocation. Within the actual user_add function, you will find the following:

Code: Select all
// call hooks
$hook_handler->invoke_hook('user_add', array($sql_ary, $cp_data));

This calls all hooks that bound to ‘user_add’, passing the two arguments into them. There will be quite a few of these hook locations to take advantage of, and they will always provide a context that you can work with.

As a MODification author you will also be able to provide your own hook locations to other MOD writers. All it takes is a call to invoke_hook, which will allow others to hook into your code.

There are some more advanced features about hooks, such as (un)installing, enabling/disabling, prioritising hooks. But I’ll save that for later.

In summary

  • class with methods representing hooks
  • invoke_hook will call all hooks that registered
  • hooks are automagic

So now that you understand the basics regarding hooks, I hope you can look forward to this great addition in ascraeus and help us by contributing Hook Location Requests.