CLOSE
Updated on 11 Jul, 202617 mins read 30 views

Introduction

In the previous chapters, we answered two important questions:

Why do hook systems exist?

and

Why are callbacks a better solution than hardcoding behavior?

Now we're going to do something much more interesting.

Instead of simply using a hook system, we're going to build one mentally.

By the end of this chapter you'll understand exactly how frameworks like:

  • WordPress
  • Botble CMS
  • Unreal Engine Delegates
  • Qt Signals & Slots
  • C# Events
  • Laravel Events

internally organize callbacks.

Once you understand the architecture, every hook system suddenly looks almost identical.

What Does a Hook Manager Actually Do?

Imagine plugins registering themselves.

Plugin A says

"Call me when a post is saved."

Plugin B says

"Call me too."

Plugin C says

"Call me before Plugin B."

The framework has to remember all of this.

So the framework needs a central manager.

             +---------------------+
             | Hook Manager        |
             +---------------------+
             | Registered Hooks    |
             | Priorities          |
             | Callbacks           |
             +----------+----------+
                        |
        +---------------+---------------+
        |               |               |
     Plugin A        Plugin B       Plugin C

Everything revolves around one object.

Why Information Must be Stored?

Suppose someone writes:

addFilter(
    "save_post",
    callback,
    priority = 20,
    arguments = 2
);

What should be remembered?

Four things.

Hook Name = save_post
Callback = callback()
Priority = 20
Argument Count = 2

Every registration becomes one record.

{
    hook = save_post
    callback = callback
    priority = 20
    arguments = 2
}

Multiple Plugins Registers

Plugin A: priority 20
Plugin B: priority 10
Plugin C: priority 50

Internally we have:

save_post:
	20 -> Plugin A
	10 -> Plugin B
	50 -> Plugin C

Notice something:

  • They are not stored in execution order.
  • They are simply stored.
  • Execution order comes later.

Organizing by Hook Name

Instead of storing one huge list:

Plugin A
Plugin B
Plugin C
Plugin D

Frameworks organize them by hook.

save_post
	Plugin A
	Plugin B
	Plugin C
login
	Plugin X
	Plugin Y

Much cleaner.

A Better Data Structure

Think of a dictionary.

Hook Name
      ↓
Callbacks
save_post
        ↓
     callbacks

render
      ↓
 callbacks

login
      ↓
 callbacks
In C++: unordered_map
In PHP: array
In Java: HashMap

Conceptually:

Hook Name
	↓
List of callbacks

Adding Priorities

Now we need ordering.

Instead of:

save_post
	↓
callbacks

we make:

save_post
	↓
priority
	↓
callback
save_post
	10
		callback
	20
		callback
	50
		callback

Now execution becomes predictable.

Complete Internal Layout

Hooks
	↓
	save_post
		↓
		10
 callback
		20
 callback
		50
 callback
	render_page
		↓
		5
 callback
		15
 callback

Registration Phase

When plugins load:

Plugin A
	addFilter(...)

Hook Manager stores it.

listeners
	↓
	save_post
		↓
		20
 callback

Nothing executes. Only registration.

Plugin B registers.

listeners
	↓
	save_post
		↓
		20
 callback
		10 callback

Still nothing executes.

Plugin C registers.

listeners
	↓
	save_post
		↓
		20
 callback
		10 callback
		50 callback

The system is only collecting information.

Execution Phase

Later…

Someone calls

applyFilters("save_post", value);

The hook manager performs four steps.

Step 1: Find the hook

save_post
	↓
	callbacks

Step 2: Sort priorities

10
20
50

Step 3: Call each callback

callback()
↓
callback()
↓
callback()

Step 4: Return the final value

Original
	↓
Plugin A
	↓
Plugin B
	↓
Plugin C
	↓
Final

Done.

Why Registration and Execution Are Separate

This is important architectural decision.

Imagine execution happened immediately.

addFilter()
	↓
execute callback

That would make no sense.

At startup

  • plugins are still loading
  • routes aren't created
  • services aren't ready
  • database may not be connected.

Instead:

Frameworks do

Register Everything
	↓
Later....

Fire Hooks

This separation makes initialization deterministic.

Why Priorities Matter

Imagine:

Plugin A compresses HTML
Plugin B inserts analytics
Execution order matters

Correct:

Analytics
	↓
Compression

Wrong:

Compression
	↓
Analytics

Analytics might break.

Priorities solve this.

The Hook Manager's Responsibilities

A hook manager actually has only five responsibilities.

  1. Register callbacks.
  2. Organize callbacks by hook.
  3. Maintain execution order.
  4. Execute callbacks.
  5. Return the final result (for filters).

Everything else is just implementation detail.

Real Framework Mapping

Every mature framework follows this same architecture.

FrameworkRegistrationExecution
WordPressadd_filter()apply_filters()
WordPressadd_action()do_action()
Botble CMSadd_filter()apply_filters()
Botble CMSadd_action()do_action()
Qtconnect()emit
C#+=event()
UnrealAddDynamic()Broadcast()
LaravelEvent::listen()Event::dispatch()

The names differ, but the underlying workflow remains remarkably consitent.

Buy Me A Coffee

Leave a comment

Your email address will not be published. Required fields are marked *

Your experience on this site will be improved by allowing cookies Cookie Policy