In a local Laravel app, how does Laravel Debugbar help find why a cart page loads slowly or shows a wrong total, and when does it enable itself?
answer
- composer require --dev, auto-discovered
- queries tab with bindings and source
- timeline and startMeasure()
- views tab lists rendered templates
- APP_DEBUG on, not production or testing
basics
~20 sDebugbar injects a toolbar into local HTML pages showing every query with bindings and source line, a timeline, rendered views, log messages and more. It enables itself only when APP_DEBUG is true, the environment is not production or testing, and never in the console.
solid answer
~40 sInstall it with `composer require fruitcake/laravel-debugbar --dev` (the package that replaces `barryvdh/laravel-debugbar`); auto-discovery registers it and it injects a bar before `</body>`. For a slow or wrong cart page, the **queries** tab lists every statement with bindings substituted, its duration and the file that issued it, so you spot 40 repeated promotion lookups or a query missing a condition. The **timeline** splits booting from application time, and `Debugbar::measure()` or `startMeasure()`/`stopMeasure()` time your discount code. The **views** tab lists rendered templates; messages show `debug($value)` calls and log entries. It enables only when `APP_DEBUG` is true and the environment is not `production` or `testing` (unless `force_allow_enable` is set), then follows `DEBUGBAR_ENABLED`, and never runs in the console.
code
php · 14 lines<?php
use Fruitcake\LaravelDebugbar\Facades\Debugbar;
public function total(Cart $cart): int
{
return Debugbar::measure('Cart discounts', function () use ($cart) {
$discount = $this->rules->apply($cart);
Debugbar::info(['cart' => $cart->id, 'discount' => $discount]);
return $cart->subtotal - $discount;
});
}go deeper
Know that Debugbar is a dev-only toolbar showing queries, time and views, and that it appears when APP_DEBUG is on locally.
Walk through the enable rules, the key collectors and their defaults, and how measure() and debug() add your own data.
Use query counts, bindings and backtraces to diagnose repeated or wrong queries, and keep Debugbar out of shared environments and production builds.
Decide which debugging tools the team standardises on locally and which recorded-history tools, if any, are allowed on shared environments.
## What Debugbar is **Laravel Debugbar** integrates the PHP Debug Bar library with Laravel. On each HTML response it injects a toolbar at the bottom of the page whose tabs, called **collectors**, show what happened during that request. It also captures AJAX and Livewire requests and lists them in a dropdown. In Debugbar 4 the package is published as `fruitcake/laravel-debugbar`, which declares that it replaces `barryvdh/laravel-debugbar`. ```bash composer require fruitcake/laravel-debugbar --dev php artisan vendor:publish --provider="Fruitcake\LaravelDebugbar\ServiceProvider" ``` The second command is optional; it publishes `config/debugbar.php`. ## When it switches on `LaravelDebugbar::canBeEnabled()` and `isEnabled()` decide, in this order: 1. If `debugbar.force_allow_enable` (`DEBUGBAR_FORCE_ALLOW_ENABLE`) is true, the environment checks are skipped. 2. Otherwise it requires **debug mode on** and an environment that is **not `testing` or `production`**. 3. Then `debugbar.enabled` (`DEBUGBAR_ENABLED`) decides; when it is `null`, the default, it follows `config('app.debug')`. 4. It is always off when running in the **console**, so Artisan commands and queue workers never collect. The `except` list skips URIs such as `telescope*` and `horizon*`. ## Collectors that find a wrong discount or a slow page | Collector (config key) | Default | What it shows | |---|---|---| | Queries (`db`) | on | every query, bindings substituted, duration, the source file and line via backtrace, optional EXPLAIN | | Time (`time`) | on | a timeline from boot to response; custom measures appear here | | Views (`views`) | on | each rendered view; view data only if `options.views.data` is enabled | | Messages (`messages`) and Log (`log`) | on | `debug()` calls and log entries from the request | | Models (`models`) | on | how many Eloquent models of each class were loaded | | Route (`route`), Session (`session`), Events (`events`), Config (`config`) | off | enable in `collectors` when needed | For the grocery cart: - **Slow page:** the queries tab shows the count and total time. Forty near-identical `select * from promotions where product_id = ?` lines, each traced to the same Blade partial, point straight at a lookup inside a loop. The models tab confirming hundreds of `Promotion` models loaded tells the same story. - **Wrong total:** the queries tab shows the exact bindings used, for example a `category_id` of the wrong category or a missing `active = 1`, which is often the whole bug. - **Where time goes:** wrap the calculation in `Debugbar::measure('discounts', fn () => ...)` and read its bar on the timeline. The query collector has limits: after `soft_limit` (100) queries it stops capturing parameters and backtraces, and after `hard_limit` (500) it ignores further queries. ## Adding your own data ```php use Fruitcake\LaravelDebugbar\Facades\Debugbar; Debugbar::info($cart->total); Debugbar::startMeasure('discount', 'Discount calculation'); // ... Debugbar::stopMeasure('discount'); debug($rule); // helper: adds a message ``` Unlike `dump()`, these calls leave the page layout intact and put the data in the bar. ## Debugbar compared with other tools | Tool | Scope | Good for | |---|---|---| | `dump()` / `dd()` | one value, one point in code | quick local inspection | | Debugbar | the current page and its AJAX calls | queries, timing, views of a request you are looking at | | Logs | any process, kept over time | jobs, APIs, production | Debugbar sits in the middle: richer than a dump, but only for requests you load in a browser. ## Keeping it out of production - Install it as a **dev** dependency so `composer install --no-dev` never ships it. - Its own README warns never to use it on publicly accessible sites: it stores request data (by default as files under `storage/debugbar`) and shows queries, views, session and request details **by design**. - It also slows requests while collecting; disable collectors you do not need. The environment check means `APP_DEBUG=true` alone on a server whose `APP_ENV` is `production` does not enable it, but a staging server with a different `APP_ENV` and debug on will show it to anyone.
- You set DEBUGBAR_ENABLED=true on a server with APP_ENV=production and APP_DEBUG=true. Does the bar appear?No. `canBeEnabled()` runs first and returns false when the environment is `production` or `testing`, whatever `debugbar.enabled` says. Only `force_allow_enable` bypasses that check. APP_DEBUG=true in production is still a serious leak on its own, through the exception page.
- Why does Debugbar show nothing for a slow queued job?Debugbar is disabled when the app runs in the console, and queue workers run through Artisan. For jobs, use logs with timing context, or a tool that records jobs, such as Telescope's job watcher or a queue dashboard.
saying these in an interview costs you the question
- Setting DEBUGBAR_ENABLED=true is enough to show it in production.
- Debugbar should be installed as a normal dependency so staging has it.
- The views tab shows each view's data by default.
- Debugbar collects queries from Artisan commands and queue workers.
- Debugbar data is only held in memory and never stored.