bavix/laravel-xhprof
Integrates XHProf profiling into Laravel so you can capture and inspect performance data for requests and identify slow endpoints. Provides simple configuration and middleware for lightweight, request-level profiling.
bavix/laravel-xhprof wraps the XHProf (or tideways_xhprof) PHP profiler so a Laravel app can be profiled per-request and the resulting callgraphs browsed from a built-in UI. Release 2.1.0 is a compatibility release — it adds Laravel 13 support alongside the existing 10/11/12 range, plus dependabot workflow bumps. There are no breaking changes, so upgrading from 2.0.x is a routine composer update.
php -m | grep -i xhprof (or tideways_xhprof) before installing anything, and check the extension builds against your PHP version — that is the step teams most often get stuck on.composer require bavix/laravel-xhprofphp artisan vendor:publish --tag=xhprof (confirm the tag with php artisan vendor:publish if it differs). The config lands at config/xhprof.php.XHPROF_ENABLED=true in .env./xhprof) and read the wall-time and inclusive/exclusive time columns for the slowest frames. That single loop — enable, hit, inspect — is 90% of day-to-day use.Look first at: config/xhprof.php (what gets profiled and where profiles are stored), then the middleware the package auto-registers — that is the thing that decides whether your request is captured at all.
Targeted profiling via middleware. Rather than profiling everything, keep global capture off and apply the package middleware to the specific route groups you care about (a slow checkout endpoint, an API group under load). This keeps profile storage small and keeps overhead away from high-traffic paths.
Global sampling mode. For "what's slow in production-like traffic" work, enable the global capture option together with a sampling rate below 1 so only a fraction of requests are profiled. Pair this with a short retention window so profile files don't accumulate.
Environment-gated config. Drive the config from env rather than editing config/xhprof.php directly, so local, CI, and staging can differ without merge conflicts. Guard the enable flag with something that can never be true in production unless deliberately set.
Before/after optimisation loop. Snapshot a profile on the current code, apply the optimisation, snapshot again, and compare the same route with comparable input. XHProf callgraphs are only meaningful as a comparison — absolute wall times drift with machine state.
Pair with query logging. XHProf shows PHP call frames; it does not show SQL. For anything database-shaped, read the profile for the PHP frame that's hot, then reproduce with DB::listen or Telescope to see the query. The two together are what actually find the problem.
Storage lifecycle in CI and local dev. Add the profile storage directory to .gitignore, and schedule the package's clear/prune command (check php artisan list xhprof) so a long-lived dev box doesn't fill its disk. In CI, leave profiling disabled entirely.
Upgrade path for 2.1.0. If you're on Laravel 13 you were previously blocked; 2.1.0 unblocks you. Update the constraint, run the suite, and smoke-test one profiled request — the release is dependency/CI churn plus framework support, so the risk surface is the framework matrix, not the package internals.
xhprof/tideways_xhprof extension usually manifests as silent non-profiling or a fatal on the first profiled request rather than a clean install-time error. Verify the extension independently with a one-line xhprof_enable() script before blaming the package.php artisan route:clear/config:clear after config edits resolves a surprising number of "it's not working" reports.config/xhprof.php read through env vars requires php artisan config:cache to be re-run on deploy; a stale cache is the classic reason an env toggle "does nothing".illuminate/* and PHP constraints in composer.json before bumping — 2.1.0 widens framework support but does not change your PHP floor.How can I help you explore Laravel packages today?