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.
Leave a comment
Your email address will not be published. Required fields are marked *
