Skip to main content

Should we document every PHP function — and how?

· 3 min read
Jon-Michael Lastimosa
Senior Web Developer

The question: UnysonPlus has a large PHP surface — ~845 public-prefixed helper functions and ~350 actions/filters. Is it wise to document all of it, the way people mean when they say "document every function"? And if so, how — hand-written pages, or generated?

Context

Documenting functions inline and publishing a browsable reference is a standard, named practice: docblocks (PHPDoc / PSR-5/19) parsed by doc generators (phpDocumentor, Doxygen; JSDoc, Javadoc, rustdoc elsewhere). WordPress itself ships the Code Reference auto-generated from PHPDoc via phpdoc-parser. In the Diátaxis documentation model (Tutorials / How-to / Reference / Explanation), a function catalogue is squarely Reference — a different axis from our existing how-to Manual, The Theme, and AI Dev Kit sections.

The temptation is to generate a page per symbol for all ~845 functions. That's the classic trap: exhaustive auto-references become dumping grounds nobody reads, they go stale the moment a signature changes, and 90% of the entries are internal helpers meaningless without their surrounding code.

Options considered

  • A — Hand-write a reference. Highest quality per page, but unmaintainable at this scale and guaranteed to drift from the code. Rejected outright.
  • B — Auto-generate a page per function for everything (WP-style). Comprehensive, but noisy and low-signal; buries the ~5% that authors actually consume (public helpers + hooks) under internal plumbing. This is the "dumping ground" outcome.
  • C — Generate a reference for the public contract only, organized by subsystem. The public helper functions (the fw_ / unysonplus_ / upw_ / sc_ / fw_ext_ families) and — with equal billing — every framework-owned hook, since hooks are the real extensibility surface a framework lives or dies by. Internal closures and WordPress-core hooks are excluded on purpose.

Decision

Option C. The docs site gets a dedicated, generated API Reference section (/reference), split into Functions and Hooks, each grouped by subsystem. It's produced by a two-step pipeline — scripts/extract-php-api.php (a token_get_all scan that pulls signatures, docblocks, function_exists()-guarded/pluggable flags, and do_action/apply_filters sites) → scripts/gen-php-api.mjs (emits the grouped Markdown). The .md is generated, never hand-authored: you edit the framework docblocks and re-run the two commands.

Implementation stance: the code documents the implementation (via docblocks); the site documents the contract people depend on (public API + hooks).

Why

  • Signal over noise. Authors search for "which function formats an upload path" or "which filter lets me change X" — the public helpers and hooks. Those are exactly what's published; the internal 90% stays where it belongs (in the source, next to the code it explains).
  • It can't drift. Because it's extracted from the shipped source every build, the reference always matches the code — the failure mode that kills hand-written and even per-symbol-generated references.
  • Hooks are first-class. For a framework, the hook catalogue is the single highest-value reference — it's the supported way to extend without forking. Giving it a peer section to Functions reflects that.
  • It slots into the existing IA. As a Diátaxis Reference section it sits cleanly beside the how-to Manual / The Theme / AI Dev Kit rather than competing with them.

Status: Accepted — the generated section ships with the functions + hooks pipeline; future framework changes flow through by re-running the extractor + generator.