Weave Code
Weaver
Helps Laravel developers discover, compare, and choose open-source packages. See popularity, security, maintainers, and scores at a glance to make better decisions.
Feedback
Share your thoughts, report bugs, or suggest improvements.
Subject
Message

Chromephp Laravel Package

ccampbell/chromephp

ChromePhp sends PHP logs and variables directly to the Chrome DevTools console using the Chrome Logger protocol, so you can debug without cluttering page output or digging through server logs. Just include the class and call ChromePhp::log().

Deep Wiki
Context7

Getting Started

ccampbell/chromephp is a single-class, zero-dependency library that sends PHP variables to the Chrome DevTools console via the X-ChromeLogger-Data response header.

Minimal setup:

composer require ccampbell/chromephp
require __DIR__ . '/vendor/autoload.php';

ChromePhp::log('Hello from PHP');
ChromePhp::log($user);
ChromePhp::warn('Payment failed', $payload);

Then:

  1. Install the Chrome Logger browser extension (or use Clockwork, which understands the same protocol).
  2. Open DevTools → Console.
  3. Reload the page; the PHP values appear inline with your JavaScript logs.

Where to look first:

  • ChromePhp.php — the entire package is one class. Scan the public static methods near the bottom: log(), info(), warn(), error(), group(), groupCollapsed(), groupEnd(), table(), trace(), setEnabled(), addSetting().
  • The README for the extension/protocol details and the X-ChromeLogger-Data header format.

First useful case: debugging a Laravel controller or service without breaking the response.

public function show(User $user)
{
    ChromePhp::log('Loading user', $user->id);
    ChromePhp::table($user->only(['id', 'email', 'created_at']));

    return view('users.show', compact('user'));
}

If nothing appears in the console, inspect the Network tab response headers for X-ChromeLogger-Data before assuming the logging call failed.

Implementation Patterns

Use it as a “dump without dying” tool. Unlike dd() or var_dump(), ChromePhp does not interrupt the response. This makes it useful in controllers, service classes, model observers, and Blade views where you still need the page to render.

ChromePhp::info('Order totals', [
    'subtotal' => $order->subtotal,
    'tax'      => $order->tax,
    'total'    => $order->total,
]);

Group related logs. Groups keep console output readable when debugging multi-step flows.

ChromePhp::group('Checkout');
ChromePhp::log('Validating cart', $cart->id);
ChromePhp::log('Applying coupon', $coupon);
ChromePhp::groupEnd();

Use tables for collections. ChromePhp::table() is useful for arrays of arrays or simple objects; it renders as a console table.

ChromePhp::table(
    $users->map(fn ($u) => ['id' => $u->id, 'email' => $u->email])->all()
);

Enable only in local/development environments. Because the data is sent to the browser, it should never be active in production. In a Laravel AppServiceProvider::boot():

ChromePhp::setEnabled(app()->environment('local', 'development'));

Or at the top of a bootstrap file:

if (php_sapi_name() !== 'cli' && getenv('APP_ENV') === 'local') {
    ChromePhp::setEnabled(true);
} else {
    ChromePhp::setEnabled(false);
}

Wrap it behind a small helper. Direct static calls are fine, but a wrapper makes it easy to switch to Ray, Clockwork, or Laravel Telescope later.

final class Debug
{
    public static function log(mixed ...$args): void
    {
        if (app()->environment('local')) {
            ChromePhp::log(...$args);
        }
    }
}

Use it with JSON and AJAX responses. The payload is a response header, so it can still be delivered on XHR/fetch responses even if the body is JSON. Avoid echo/var_dump in these endpoints; log to ChromePhp instead.

Add backtraces when tracing call sites. Use the setting API to include file/line context:

ChromePhp::addSetting(ChromePhp::BACKTRACE, true);
ChromePhp::trace('Where did this run?');

Disable it in test suites. Static state can leak between tests. Call ChromePhp::setEnabled(false) in phpunit bootstrap or TestCase::setUp(), then explicitly enable it only in debugging tests.

Framework integration tip. There is no Laravel service provider or PSR-3 adapter. Treat it as a development-only utility rather than a logging backend. For production logging, keep Laravel’s Log facade; for local debugging, use ChromePhp.

Gotchas and Tips

  • Headers must not have been sent yet. Any prior output — whitespace, BOM, echo, var_dump, header() calls, or a framework’s streaming response — can prevent ChromePhp from delivering logs. If output is already flowing, enable output buffering or log earlier.

  • Header size limits are real. The encoded payload travels in an HTTP header. Web servers, FastCGI, proxies, and CDNs impose limits (often around 8 KB, sometimes less). Logging a huge collection or deeply nested object can cause truncated logs, 502/431 responses, or missing console output. Log IDs, counts, or slices instead.

    ChromePhp::log('Large result', [
        'count' => count($rows),
        'first' => array_slice($rows, 0, 5),
    ]);
    
  • Do not log secrets, even locally. The data is sent in the response and is visible to anyone who inspects it. If the browser extension is absent, the header is still there in the Network tab.

  • CLI and queue workers cannot use it. There is no HTTP response to attach headers to. Guard calls with php_sapi_name() !== 'cli' or environment checks.

  • Serialization can fail silently. Resources, closures, circular object graphs, and invalid UTF-8 strings may not encode properly. Convert models/DTOs to arrays, use JsonSerializable, or sanitize strings before logging.

  • The Chrome extension is old and unmaintained. Modern Chrome may still run it, but installation friction is common. Clockwork or Ray are more actively maintained alternatives and understand similar debugging workflows.

  • Proxies and CDNs may strip unknown headers. If logs work locally but not behind Nginx, Cloudflare, or a load balancer, check whether X-ChromeLogger-Data is being forwarded.

  • Cross-origin XHR may need header exposure. For cross-origin requests, the browser may not expose custom response headers to tooling unless Access-Control-Expose-Headers includes X-ChromeLogger-Data.

  • Static state and singletons. ChromePhp is a global static utility. Enabling/disabling it affects the whole process, and logs accumulate in memory until sent. Avoid subclassing it for customization; wrap it instead.

  • Balance groups. Every ChromePhp::group() should have a matching ChromePhp::groupEnd(), or the console can remain nested for subsequent logs.

  • Debugging when nothing appears. Check three things in order: (1) the X-ChromeLogger-Data header exists in the Network tab, (2) the browser extension is installed and enabled for the site, and (3) no output/headers were sent before the ChromePhp call.

  • Prefer early logging. If the script dies with a fatal error or exits before the payload is flushed, logs may be lost. Log at the point of interest rather than relying on a shutdown flush.

  • Keep it out of production deploys. Disable it globally, remove ad-hoc calls before merging, and prefer a wrapper or conditional helper so the application does not accidentally ship debugging payloads to users.

Weaver

How can I help you explore Laravel packages today?

Conversation history is not saved when not logged in.
Prompt
Add packages to context
No packages found.
coleus/frame
thtg88/journalism
filagora/filagora-ai-forums
rlacerda83/query-parser
socialdept/atp-orm
cboxdk/laravel-assistant-client
socialdept/atp-resolver
socialdept/tenant-domains
tautvydasr/blade-class-names
socialdept/color-scales
maherelgamil/controller
coleus/widgets
coleus/table
coleus/users
coleus/music
coleus/health
coleus/calendar
coleus/notes
coleus/support
coleus/settings