Search by

sfaut / insight

sfaut

Readable var_dump()/print_r() alternative with a colored CLI renderer and a collapsible HTML renderer, configurable truncation, and circular-reference detection.

v0.1.0 2026-09-12 19:01 UTC

This package is auto-updated.

Last update: 2026-09-12 19:20:16 UTC


README

license tests

A PHP library that inspects a variable and renders a readable representation of it, the way var_dump() or print_r() do -- with a colored CLI renderer and a collapsible HTML renderer, both built from the same introspection pass.

PSR-4 root namespace sfaut\Insight\, no dependency on any framework or application code -- usable as a standalone package.

Why

var_dump() is noisy -- a type name on every scalar, a length on every string, an object(Class)#N (M) wrapper, ["prop":"Class":private] decorations on every property -- and gives no way to bound how much of a deep or wide structure gets printed short of writing your own recursive walker. print_r() is quieter but loses type information and offers the same lack of control. Neither one gives you HTML output or independent truncation limits for arrays, strings, and nesting depth.

Insight aims for var_dump()-level detail with print_r()-level readability: bare scalars, a quoted string with no length suffix, an object's own class name with no object(...) wrapper, property names as plain quoted strings with only a visibility symbol (+/#/) -- and, on top of that, configurable head/tail truncation for arrays (independently for list-shaped, map-shaped, and sparse arrays), for long strings, for multiline strings, and for nesting depth, plus circular-reference detection for both objects and arrays.

What it looks like

use sfaut\Insight\Insight;

Insight::view([
    'id' => 42,
    'name' => 'Widget',
    'price' => 19.99,
    'tags' => ['new', 'sale'],
    'shape' => $circle,
]);
map:5 [
    "id" => 42
    "name" => "Widget"
    "price" => 19.99
    "tags" => list:2 [
        0 => "new"
        1 => "sale"
    ]
    "shape" => Circle:3 {
        +"radius" => 2.5
        −"color" => "red"
        #"count" => 1
    }
]

Colored when run in an interactive terminal (auto-detected), plain text when piped or redirected, or a collapsible HTML block when running outside the CLI SAPI -- no configuration needed for either switch.

Requirements

PHP 8.4+. (The library's own code under src/ only uses PHP 8.1-level language features -- enums, readonly properties, array_is_list() -- but the dev tooling, pestphp/pest ^5.1, requires PHP 8.4+, so that's the honest floor for the published package too.)

Installation

composer require sfaut/insight

Usage

The facade

use sfaut\Insight\Insight;

Insight::view($v);                    // echoes the rendered dump, plus a trailing newline
$dump = Insight::render($v);          // returns the rendered dump as a string instead
Insight::write('/tmp/dump.txt', $v);  // writes it to a file

Every method takes the same per-call $options array as its last argument, merged on top of the current global configuration for that one call only:

Insight::view($v, ['maxDepth' => 2, 'maxListBeginElements' => 5]);

Global configuration

Insight::configure(['colors' => false, 'indentSize' => 2]);
Insight::view($v); // now uses 2-space indentation, no color
Insight::reset();  // back to the built-in defaults

Truncating a large collection

Arrays are shown as a head + tail preview once they exceed their configured limits, which are independent for list-shaped (array_is_list()), map-shaped (at least one string key), and sparse arrays:

Insight::view(range(1, 30), ['maxListBeginElements' => 3, 'maxListEndElements' => 2]);
list:30 [
    0 => 1
    1 => 2
    2 => 3
    … (25 more items)
    28 => 29
    29 => 30
]

Each of the six max{List,Map,Array}{Begin,End}Elements options independently controls one side of one array shape. null on a given side means that side contributes nothing -- not "no limit", but "show zero items from there":

  • maxListBeginElements: null, maxListEndElements: 5 -- shows only the last 5 items, nothing from the start.
  • maxListBeginElements: null, maxListEndElements: null -- both sides contribute nothing to truncate against, which is the one case handled as "no truncation at all": the array is always shown in full.
  • A collection that already fits within begin + end is also shown in full, with no gap, regardless of the limits.

Object properties are never truncated by count, and objects are always walked in full regardless of maxDepth -- only arrays get cut off by depth (rendered as *DEEP*).

Circular references

Both an object referencing itself and an array containing a reference to itself ($a['self'] = &$a;) are detected and rendered as *RECURSION* instead of looping forever:

$node = new Node();
$node->next = $node;

Insight::view($node);
Node:1 {
    +"next" => *RECURSION*
}

HTML output

Insight::view($v, ['format' => 'html']); // force HTML regardless of PHP_SAPI

format defaults to auto-detecting PHP_SAPI ('cli' on the command line, 'html' otherwise); colors defaults to auto-detecting whether STDOUT is an interactive TTY.

The main configuration options

Option Type Default Role
maxDepth int 10 Nesting levels walked before an array is truncated (*DEEP*); objects are always walked in full.
maxListBeginElements / maxListEndElements int|null 20 / 20 Items kept at the start/end of a list-shaped array.
maxMapBeginElements / maxMapEndElements int|null null / null Same, for a map-shaped array (at least one string key).
maxArrayBeginElements / maxArrayEndElements int|null 20 / 20 Same, for a sparse/non-zero-based array.
indentSize int 4 Spaces (CLI) or characters (HTML) per indentation level.
maxStringLength int 100 Characters shown for a single-line string before truncation.
maxStringLines / maxLineLength int 4 / 100 Lines shown for a multiline string, and characters shown per line, before truncation.
colors bool|null null Force ANSI colors on/off in CLI; null auto-detects the TTY.
format string|null null Force 'cli' or 'html'; null auto-detects from PHP_SAPI.

maxStringLength and maxLineLength count and cut in UTF-8 characters (mb_strlen()/ mb_substr()), not bytes -- a multi-byte character is never split in half.

See the docblock on sfaut\Insight\Config's constructor for the full, authoritative list.

Limitations

  • Circular-reference detection for arrays only covers a reference created directly in the array ($a[] = &$a;); a cycle reached through an object property is bounded by maxDepth instead (*DEEP*), without an explicit *RECURSION* marker -- reading a property through reflection copies its value and loses the reference.
  • Class constants and methods are never shown on an object -- only its properties, to keep the dump focused on state rather than definition.
  • A Closure is inspected like any other object; since it exposes no reflectable properties, it always renders as Closure:0 {}.
  • CLI colors are a single fixed palette -- there is no theme/palette option to customize them. The HTML renderer's colors are likewise fixed in an embedded stylesheet, adapting to light/dark via prefers-color-scheme.

License

MIT -- see LICENSE.