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 CEverything 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 = 2Every 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 50Internally we have:
save_post:
20 -> Plugin A
10 -> Plugin B
50 -> Plugin CNotice 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 DFrameworks organize them by hook.
save_post
Plugin A
Plugin B
Plugin Clogin
Plugin X
Plugin YMuch cleaner.
A Better Data Structure
Think of a dictionary.
Hook Name
↓
Callbackssave_post
↓
callbacks
render
↓
callbacks
login
↓
callbacksIn C++: unordered_map
In PHP: array
In Java: HashMapConceptually:
Hook Name
↓
List of callbacksAdding Priorities
Now we need ordering.
Instead of:
save_post
↓
callbackswe make:
save_post
↓
priority
↓
callbacksave_post
10
callback
20
callback
50
callbackNow execution becomes predictable.
Complete Internal Layout
Hooks
↓
save_post
↓
10
callback
20
callback
50
callback
render_page
↓
5
callback
15
callbackRegistration Phase
When plugins load:
Plugin A
addFilter(...)Hook Manager stores it.
listeners
↓
save_post
↓
20
callbackNothing executes. Only registration.
Plugin B registers.
listeners
↓
save_post
↓
20
callback
10 callbackStill nothing executes.
Plugin C registers.
listeners
↓
save_post
↓
20
callback
10 callback
50 callbackThe 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
↓
callbacksStep 2: Sort priorities
10
20
50Step 3: Call each callback
callback()
↓
callback()
↓
callback()Step 4: Return the final value
Original
↓
Plugin A
↓
Plugin B
↓
Plugin C
↓
FinalDone.
Why Registration and Execution Are Separate
This is important architectural decision.
Imagine execution happened immediately.
addFilter()
↓
execute callbackThat 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 HooksThis separation makes initialization deterministic.
Why Priorities Matter
Imagine:
Plugin A compresses HTML
Plugin B inserts analytics
Execution order mattersCorrect:
Analytics
↓
CompressionWrong:
Compression
↓
AnalyticsAnalytics might break.
Priorities solve this.
The Hook Manager's Responsibilities
A hook manager actually has only five responsibilities.
- Register callbacks.
- Organize callbacks by hook.
- Maintain execution order.
- Execute callbacks.
- Return the final result (for filters).
Everything else is just implementation detail.
Real Framework Mapping
Every mature framework follows this same architecture.
| Framework | Registration | Execution |
|---|---|---|
| WordPress | add_filter() | apply_filters() |
| WordPress | add_action() | do_action() |
| Botble CMS | add_filter() | apply_filters() |
| Botble CMS | add_action() | do_action() |
| Qt | connect() | emit |
| C# | += | event() |
| Unreal | AddDynamic() | Broadcast() |
| Laravel | Event::listen() | Event::dispatch() |
The names differ, but the underlying workflow remains remarkably consitent.



Join the discussion
Sign in with your account to post comments, reply to others, and participate in the conversation.
Login to Comment