zappzarapp / devtoolbar
In-app developer toolbar for PHP applications: timeline, query analyzer, HTTP/cache collectors, exception tracking, request history. Ships the JS UI as a bundled asset (symfony/web-profiler-bundle pattern).
Requires
- php: ^8.4
- monolog/monolog: ^3.0
- zappzarapp/security: ^1.0
Requires (Dev)
- captainhook/captainhook: *
- captainhook/plugin-composer: ^5.3
- cyclonedx/cyclonedx-php-composer: ^6.1
- deptrac/deptrac: ^4.5
- ekino/phpstan-banned-code: ^3.0
- friendsofphp/php-cs-fixer: ^3.91
- infection/infection: *
- phpmd/phpmd: ^2.15
- phpstan/phpstan: ^2.1
- phpunit/phpunit: ^13.0
- rector/rector: ^2.3
- roave/security-advisories: dev-latest
- vimeo/psalm: ^6.14
Suggests
- ext-curl: Required when HttpClientCollector tracks cURL-based HTTP clients
- ext-redis: Required when CacheCollector is wired to a Redis backend
This package is auto-updated.
Last update: 2026-08-15 15:43:44 UTC
README
In-app developer toolbar for PHP applications. Renders a mini-bar overlay with collectors for queries, HTTP requests, cache operations, exceptions, timeline phases, and request history, with N+1 detection and configurable performance alerts.
The JavaScript UI ships as a pre-built asset of this PHP package (the
symfony/web-profiler-bundle
pattern): composer require is all a consumer needs — no Node toolchain, no
npm install.
Requirements
- PHP 8.4+
monolog/monolog^3.0 —MessageCollectorextendsAbstractProcessingHandlerzappzarapp/security^1.0 — supplies the per-request CSP nonce for the injected<script>/<style>tags
Installation
composer require --dev zappzarapp/devtoolbar
Install it as a dev dependency. The toolbar is a development-time surface and its activation guard is fail-closed (see Activation).
Usage
Boot the toolbar at the top of your front controller and register an output
buffer callback that injects the toolbar HTML before </body>:
use Zappzarapp\DevToolbar\DevToolbar; use Zappzarapp\DevToolbar\Guard\DevToolbarGuard; require __DIR__ . '/../vendor/autoload.php'; if (DevToolbarGuard::isEnabled()) { $toolbar = DevToolbar::getInstance(); $toolbar->boot(); // injectToolbar() runs when the buffer is flushed — a safe alternative // to echoing from a shutdown function. ob_start([$toolbar, 'injectToolbar']); } // ... dispatch the request and render the response as usual ...
boot() and injectToolbar() are both no-ops when the guard reports the
toolbar as disabled, so the two calls above are safe to leave in place; guard
them with isEnabled() only to avoid the output-buffer overhead in production.
Activation
DevToolbarGuard::isEnabled() is fail-closed — the toolbar stays off
unless a development environment is proven. The decision, in order:
ENABLE_DEV_TOOLBAR— an explicit on/off switch.true(any case) or1enables; anything else, including typos, disables. When set, it decides alone — the environment variables below are not consulted. This is the one deliberate override of the environment gate (e.g. to enable the toolbar on a staging system running with production-parity environment values), so pin it tofalsein production deployments.- Otherwise every set one of
APP_ENV,ENVandZAPPZARAPP_ENVmust equal one ofdev,development,local,test,testing(case-insensitive), and at least one must be set. Conflicts fail closed: a single non-development value disables the toolbar regardless of the others. - There is no list of "production" values: anything not in the development
list above —
production,prod,staging, typos, anything unknown — as well as a missing environment counts as production → disabled.
The guard also disables under the CLI SAPI and for AJAX requests. Values are
read via getenv() with an $_ENV / $_SERVER fallback, so PHP-FPM setups
running with clear_env=yes do not silently fail open.
CSP nonce
Injected inline <script> / <style> tags carry the per-request nonce from
zappzarapp/security's NonceRegistry — there is no unsafe-inline
requirement. If your application generates its own nonce, hand it to the
toolbar before boot():
$toolbar->setNonce($cspNonce);
Feeding collectors
boot() registers the default collectors and starts them. Instrument your
application by fetching a collector and recording operations as they happen:
$queries = $toolbar->getCollector('queries'); $queries?->trackQuery($sql, $bindings, $durationMs);
Available collector names: request, queries, http, cache, messages,
exceptions, timeline, history. See the classes under
Zappzarapp\DevToolbar\DataCollectors for each collector's tracking API.
Security
The toolbar exposes request internals (SQL, request/response data, exception backtraces) to anyone who can render it. Never enable it in production, and treat any environment reachable beyond localhost as production. See SECURITY.md for the full model.
License
MIT — see LICENSE.