skip to content

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?

level: middleimportance: should knowfreq 36%

answer

  1. composer require --dev, auto-discovered
  2. queries tab with bindings and source
  3. timeline and startMeasure()
  4. views tab lists rendered templates
  5. APP_DEBUG on, not production or testing

basics

~20 s

Debugbar 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 s

Install 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
<?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

for a junior

Know that Debugbar is a dev-only toolbar showing queries, time and views, and that it appears when APP_DEBUG is on locally.

for a middle

Walk through the enable rules, the key collectors and their defaults, and how measure() and debug() add your own data.

for a senior

Use query counts, bindings and backtraces to diagnose repeated or wrong queries, and keep Debugbar out of shared environments and production builds.

for a principal

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.