sebastian/exporter: Human-Readable PHP Variable Output for Test Diagnostics
Provides the functionality to export PHP variables for visualization
At a glance
- What is it?
- sebastian/exporter is a PHP library that converts any variable into a formatted string representation, handling arrays, objects, circular references, and binary strings in a way that var_dump does not. It is part of the PHPUnit ecosystem and is most useful in test frameworks that need to print failure diffs.
- Who is it for?
- sebastian/exporter is the right choice when you need consistent, readable variable output inside a PHP test framework or diagnostic tool, especially if you need custom rendering for domain objects via the ObjectExporter interface. It is not a general-purpose debugging replacement for Xdebug or a structured data serializer; if you need round-trip serialization or machine-readable output, this library is the wrong tool.
- Can I use it commercially?
- Yes. BSD-3-Clause is a permissive licence: you can use, modify and sell software built on it, as long as you keep its copyright and licence notices.
- Is it still maintained?
- Yes. The repository last received commits 1 day ago.
- What is it written in?
- Mainly PHP, according to GitHub's language statistics.
Answers come from the project's GitHub data, last synced on September 29, 2026, and from our analysis. They are not legal advice.
Editorial analysis
The Problem: var_dump Is Not Enough for Test Failures
PHP's built-in var_dump prints variable contents, but its output format is fixed, it handles circular references by printing them indefinitely until memory runs out, and it gives no compact option for large data structures. In test frameworks, failure messages need to print expected and actual values side by side in a way a developer can scan quickly. sebastian/exporter was written to fill that gap.
The library provides two main output modes. The full export mode renders every detail: array reference markers, object instance identifiers, property values, and a special notation for binary strings. The shortened export mode collapses large arrays to [...] and long strings to a prefix and suffix with an ellipsis, keeping failure messages compact.
The library is part of Sebastian Bergmann's ecosystem of PHPUnit support components and is released under the BSD-3-Clause license. The most recent releases are 8.2.1 and 8.2.0, both from 2026-08-07, and the last push to the repository was on 2026-09-26.
Installing via Composer
The library is distributed through Packagist as sebastian/exporter. For projects that need it at runtime:
composer require sebastian/exporterFor projects that only need it during testing:
composer require --dev sebastian/exporterThe README recommends the --dev flag for test suites. Composer resolves the package version constraint and places the library in vendor/. No further configuration is needed; the Exporter class is available through the SebastianBergmann\Exporter namespace once the autoloader is included.
Exporting Simple and Complex PHP Types
The Exporter class handles every PHP primitive and converts each to a predictable string. Integers and floats render as their literal values, strings are quoted, booleans render as true or false, null renders as null, NAN and negative infinity render as NAN and -INF respectively, and resources render as resource(N) of type (stream) or similar.
For arrays, the library assigns reference markers:
<?php declare(strict_types=1);
use SebastianBergmann\Exporter\Exporter;
$exporter = new Exporter;
print $exporter->export([[1, 2, 3], ['', 0, false]]);This prints output where each array is labeled with a reference number like Array &0, Array &1, so the reader can track which nested arrays are shared. The same mechanism applies to objects: each object instance gets an identifier such as stdClass Object #4, and subsequent occurrences of the same instance are printed as a reference rather than re-expanded.
Circular References and the Reference Tracking Mechanism
One of the practical reasons to use this library over var_dump is its handling of circular references. When an array contains a reference to itself, or an object holds a reference to itself, var_dump enters an infinite loop. sebastian/exporter tracks which arrays and objects it has already visited using the ExportContext, and replaces re-encountered values with a back-reference notation.
For example, a self-referencing array prints as:
<?php declare(strict_types=1);
use SebastianBergmann\Exporter\Exporter;
$array = [];
$array['self'] = &$array;
print $exporter->export($array);The output labels the inner self entry with Array &1 to match the outer array's reference identifier, making the cycle visible without looping. The same logic applies when a custom ObjectExporter is used: passing the ExportContext through nested exports ensures that reference tracking remains consistent across the entire output.
Custom Object Rendering with ObjectExporter
By default, objects are exported property by property using reflection. For domain objects with a meaningful string representation, this default is often too verbose. The library provides an ObjectExporter interface with two methods: handles(object $object): bool to declare which classes the exporter covers, and export(...): string to produce the representation.
Registering a custom exporter requires passing it to the Exporter constructor:
<?php declare(strict_types=1);
use SebastianBergmann\Exporter\Exporter;
$exporter = new Exporter(objectExporter: new MoneyExporter);
print $exporter->export(new Money(1999, 'EUR'));For projects with multiple domain types, ObjectExporterChain composes several exporters into one. Each is consulted in order; the first one whose handles() method returns true produces the output. Enums are treated as objects and are therefore passed to the exporter chain as well.
Where sebastian/exporter Falls Short
The library is designed for human-readable diagnostic output, not for serialization. The strings it produces cannot be parsed back into PHP values. It is not a replacement for serialize(), json_encode(), or a proper data mapper.
The shortened export mode collapses content aggressively: any array with more than five elements becomes [...], and strings beyond a certain length are truncated. This is intentional for keeping test output compact, but it means the shortened format loses information and is unsuitable for detailed inspection.
The library also does not produce output compatible with var_export(), which generates valid PHP syntax. If a project needs to snapshot a value and later eval() it back, this library is not the right tool.
The ObjectExporter interface is powerful, but it places full responsibility on the implementor. An object exporter that calls back into the main Exporter without passing the ExportContext through correctly will produce export output where reference numbering restarts from scratch for nested values, breaking the reference tracking for the entire export tree. The README documents this requirement explicitly, calling out the need to pass the ExportContext argument when exporting nested values.
Additionally, the README does not document thread safety or behavior under concurrent access. The library is stateless aside from the ExportContext passed during a single export call, but teams using shared state in unusual ways should verify behavior themselves.
sebastian/exporter vs. var_dump and Symfony VarDumper
PHP's var_dump is available everywhere without installation but offers no circular reference protection, no compact mode, and no way to redirect output to a string without output buffering. It is adequate for quick inspection but awkward inside test assertions.
Symfony's VarDumper component is a more feature-rich alternative. It produces HTML output for browser contexts, colors for CLI, handles circular references, and supports casters (analogous to ObjectExporter) for custom types. VarDumper is designed for interactive debugging, while sebastian/exporter targets programmatic output inside a framework. VarDumper carries the full Symfony component dependency, while sebastian/exporter is a standalone library with no external runtime dependencies beyond PHP itself.
For teams already using PHPUnit, sebastian/exporter is already present transitively. For teams building a custom test reporter or a diff-based assertion outside PHPUnit, the choice between VarDumper's richer formatting and sebastian/exporter's lighter footprint depends on whether interactive debugging features are needed.
Editorial conclusion
sebastian/exporter is the right choice when you need consistent, readable variable output inside a PHP test framework or diagnostic tool, especially if you need custom rendering for domain objects via the ObjectExporter interface. It is not a general-purpose debugging replacement for Xdebug or a structured data serializer; if you need round-trip serialization or machine-readable output, this library is the wrong tool. Before adopting it as a standalone dependency, check whether PHPUnit is already in your project, since PHPUnit pulls in sebastian/exporter transitively.
Frequently asked questions
How do I install sebastian/exporter in a PHP project?
Run composer require --dev sebastian/exporter to add it as a development dependency. The Exporter class is then available in the SebastianBergmann\Exporter namespace through Composer's autoloader.
Does sebastian/exporter handle circular references in arrays and objects?
Yes. The library tracks all visited arrays and objects via an ExportContext and replaces re-encountered values with a reference marker, preventing infinite recursion. The reference identifiers (such as Array &1) appear in the output to make the circular structure visible.
Can I customize how specific object types are rendered?
Yes. Implement the ObjectExporter interface and pass an instance to the Exporter constructor. For multiple types, wrap several ObjectExporter implementations in an ObjectExporterChain, which consults them in order and uses the first one whose handles() method returns true.
Official sources
Add this badge to your README
If you maintain this project, the badge below links readers to this analysis and shows its maintenance status from the daily GitHub snapshot. Paste the markdown into your README; add ?metric=license or ?metric=stars to the image URL for a different field.
[](https://hysenlabs.com/projects/sebastianbergmann-exporter)