A development-time toolbar your app shows at the bottom of every HTML page so you can inspect a request while it happens — memory, timing, database queries, routes, sessions, and more.
ForgeDebugBar is the debugging companion for your
app. When enabled, it automatically injects a slim,
tabbed toolbar into each HTML response. You keep
your markup untouched — the bar is appended just
before </body> along with its own
CSS and a small bit of JavaScript.
It's built around collectors: small pieces of code, each responsible for one slice of data (memory, request time, messages, route, session, and — when the router capability is around — timeline, views, exceptions, and database queries). Collectors feed the tabbed panels, so you see what happened on the request you're looking at.
Framing: this is a tool for
the person building the app, active only while
you develop. It never ships to users — when
APP_DEBUG is off, the bar simply
doesn't appear.
php forge.php package:install-module --module=forge-debug-bar
The capability needs the router and view capabilities present, and it links its public assets (the CSS and JS the bar uses) during installation:
php forge.php asset:link --type=module --module=forge-debug-bar
This makes the assets available at
/assets/modules/forge-debug-bar/ so the
injected toolbar can load them.
The bar only appears when both of these are true:
APP_DEBUG is enabled in your environment.forge_debug_bar.enabled is true (the default).On top of that, injection is careful about what it touches. It skips:
Content-Type isn't HTML (for example JSON or files).</body> tag.{"html":.The toolbar has a compact header that shows the essentials at a glance, then a set of tabs you can click to open full panels:
| Metric | Shows |
|---|---|
| Request time | Total execution time for the request, in milliseconds |
| Memory | Current memory usage (e.g. 14.30 MB) |
| PHP version | The PHP runtime the request ran on |
The Resources tab (memory panel) is always registered. The rest open up when metrics are enabled:
debug_log() messagesEach tab shows a small count badge when it has data, so you can spot at a glance which panels have something interesting.
Hub integration: when the Hub is present, the latest request's data is also stored so you can review it from the Hub's Debug Bar panel rather than digging through each page response.
Collectors are the guts of the bar. Each is a named unit that returns the data for one panel when asked. A few of the built-in ones are always active:
| Collector | What it reports |
|---|---|
memory |
Current / used / peak usage and the percent of your memory limit |
time |
Request execution time from app start |
messages |
Custom messages you logged with debug_log() |
request / session / route |
Request details, session contents, and the matched route (metrics on) |
When metrics are enabled, the bar also adds cross-module collectors provided by the router capability — timeline, views, exceptions, and database queries — but only for the ones actually available in your app. If a collector isn't present, its tab simply stays empty.
For custom needs, you can drop in your own collector by pairing a name with a callable that returns its data:
$bar = \Modules\ForgeDebugBar\DebugBar::getInstance();
$bar->addCollector('my-plugin', function () {
return ['calls' => MyService::callCount()];
});
The most common way to use the bar from your own code
is the debug_log() helper. It records a
message (with an optional label) that shows up in
the Console tab on the current request:
debug_log('Order #123 placed', 'info');
debug_log($shippingTotal, 'amount');
Messages carry a label (default
info) and a timestamp, so you can follow
the sequence of events within a request.
A small formatBytes() helper is also
available for turning byte counts into readable units
(B, KB, MB, GB) in your own output.
Two environment variables control the bar:
| Variable | Default | Effect |
|---|---|---|
FORGE_DEBUG_BAR_ENABLED |
true |
Master on/off (must also have APP_DEBUG) |
FORGE_DEBUG_BAR_METRICS |
true |
When false, only memory/time/messages and the Resources tab run |
Turning metrics off is a quick way to
keep the bar lightweight — the request, session, and
route collectors plus the cross-module collectors and
their tabs are simply skipped, along with the
session-merge work that surfaces exceptions.
Because the bar is gated on APP_DEBUG, a
production environment with debugging off never
renders it and never runs its collectors. Its public
assets (a CSS file and a small JS file) can stay
linked without impacting real users.
Remember: keep
APP_DEBUG off in production. The debug
page your error handler shows, and this bar, both
rely on that flag — exposing stack traces or
request details to visitors would be a mistake.