Plugin Development Fundamentals
WordPress Intermediate/Advanced
Chapter 5 · Plugin Development Fundamentals
add_action( 'init', ... ) has appeared twice already, unexplained, in WordPress Intermediate/Advanced 1 and 4. This is the chapter that formally opens it up — actions and filters, the single most important WordPress-specific concept a developer needs, and the mechanism behind every plugin WordPress Fundamentals 6 ever installed as a finished product.
What a Plugin Actually Is, Structurally
Just like a theme's style.css from WordPress Intermediate/Advanced 1, a plugin needs its own specially-formatted comment header — placed at the top of a PHP file inside wp-content/plugins/ — that WordPress parses to recognize and register it.
Everything below that header is ordinary PHP — and a plugin does its actual work almost entirely by hooking functions onto actions and filters, rather than running code directly at the top level of the file.
Actions vs. Filters — The Core Distinction
| Actions | Filters |
|---|---|
| Let you do something at a specific point | Let you modify a piece of data as it passes through |
| The hooked function's return value is ignored | The hooked function must return a value — WordPress uses whatever comes back |
Registered with add_action() | Registered with add_filter() |
| Example: sending an email when a post is published | Example: shortening every post excerpt to 20 words |
add_action() — Doing Something
Every prior use of add_action( 'init', ... ) in this course follows the same shape: add_action( 'hook_name', 'function_to_run' ). WordPress calls your function at the exact moment it reaches that named point in its own execution.
This directly reuses wp_footer() from WordPress Intermediate/Advanced 1 — that function's entire job is firing the wp_footer action, giving every plugin hooked into it a chance to run.
add_filter() — Modifying Data
WordPress calls this function while generating an excerpt, passing in the current word-count limit; the function returns 20, and that's the value WordPress actually uses.
return a value doesn't leave the data unchanged — it silently replaces it with null, since a PHP function with no explicit return implicitly returns nothing. A filter hooked onto the_content that echoes debugging output instead of returning the (possibly modified) content will wipe out every post's body text entirely, with no error message anywhere pointing back to the cause.
A Small, Real Plugin — Both Mechanisms Together
This is genuinely the same category of tool WordPress Fundamentals 6 covered installing — the only difference is that this one was built from scratch, using nothing beyond ordinary PHP and the two hook functions this chapter just covered.
Priority — What Happens When Multiple Functions Hook the Same Point
add_action() and add_filter() both accept an optional priority argument (default 10) — lower numbers run earlier. Multiple plugins commonly hook the same action or filter, and priority is how their relative order is controlled when it matters.
Hands-On Exercises
A developer writes a filter function hooked to the_title that's supposed to append " — Read More" to every post title, but forgets to include a return statement. Explain exactly what visitors would see as a result.
📄 View solutionExplain, using this chapter's own compare table, whether sending a notification email when a comment is posted should be built as an action or a filter, and why.
📄 View solutionExplain what add_action( 'init', 'register_portfolio_post_type' ) from WordPress Intermediate/Advanced 4 is actually doing, now that this chapter has formally explained the mechanism behind it.
📄 View solutionChapter 5 Quick Reference
- A plugin file needs its own comment header block, parsed by WordPress, exactly like a theme's style.css
- Actions (add_action()) — do something at a specific point; return value ignored
- Filters (add_filter()) — modify a value as it passes through; the hooked function must return a value
- A filter that forgets to return silently wipes the data to null — the single most common filter mistake
- Priority (default 10, lower runs earlier) controls execution order when multiple functions hook the same point
- Every register_post_type()/register_taxonomy() call from Chapter 4 was always this exact mechanism, hooked to init
- Next chapter: The WordPress REST API