PHPackages                             componenta/var-export - PHPackages - PHPackages  [Skip to content](#main-content)[PHPackages](/)[Directory](/)[Categories](/categories)[Trending](/trending)[Leaderboard](/leaderboard)[Changelog](/changelog)[Analyze](/analyze)[Collections](/collections)[Log in](/login)[Sign up](/register)

1. [Directory](/)
2. /
3. [Utility &amp; Helpers](/categories/utility)
4. /
5. componenta/var-export

ActiveLibrary[Utility &amp; Helpers](/categories/utility)

componenta/var-export
=====================

Export PHP variables to their string representation with support for closures, arrays, and configurable formatting

v1.0.0(1mo ago)096MITPHPPHP ^8.4

Since Jun 16Pushed 1mo agoCompare

[ Source](https://github.com/componenta/var-export)[ Packagist](https://packagist.org/packages/componenta/var-export)[ RSS](/packages/componenta-var-export/feed)WikiDiscussions main Synced 1w ago

READMEChangelog (1)Dependencies (2)Versions (2)Used By (6)

Componenta VarExport
====================

[](#componenta-varexport)

[![PHP Version](https://camo.githubusercontent.com/02463ad42fbbb8e930dc93f83e8b2ecd9ad3f718d33bb429f5f8f792f9cfd2e5/68747470733a2f2f696d672e736869656c64732e696f2f62616467652f7068702d253545382e342d626c75652e737667)](https://www.php.net/)[![License](https://camo.githubusercontent.com/8bb50fd2278f18fc326bf71f6e88ca8f884f72f179d3e555e20ed30157190d0d/68747470733a2f2f696d672e736869656c64732e696f2f62616467652f6c6963656e73652d4d49542d677265656e2e737667)](LICENSE)[![Tests](https://camo.githubusercontent.com/f2e96592c65026c1e6e2d50e57b34b1145a50ec0242f14cde924d0f92632597c/68747470733a2f2f696d672e736869656c64732e696f2f62616467652f74657374732d32343325323070617373696e672d627269676874677265656e2e737667)](tests)

Round-trip PHP values to executable source code. Unlike `var_export()`, this library handles **closures**, **readonly value objects** and **enums** — and keeps namespace semantics intact so the exported code evaluates correctly anywhere.

[Русская версия](README.ru.md)

---

Features
--------

[](#features)

- **Closures** — full AST-based export with correct name resolution (class refs → FQN, function/constant refs keep global fallback)
- **Readonly value objects** — round-tripped via `new ClassName(...)` when every constructor parameter is a public property
- **Enums** — both pure and backed cases
- **Arrays** — sequential, associative, mixed, unlimited nesting (guarded by `maxDepth`)
- **Configurable output** — pretty or compact layout, custom indent, sorted keys, trailing commas
- **Typed exceptions** — precise error context without leaking the values that caused them

---

Requirements
------------

[](#requirements)

- PHP 8.4+
- `nikic/php-parser` ^5.0

Related Packages
----------------

[](#related-packages)

PackageWhy it matters here`componenta/config`Uses export for executable PHP configuration cache files.`componenta/app`Application cache can persist compiled arrays and descriptors as PHP files.`componenta/di`Compiled DI plans and dependency cache should be executable PHP arrays.`nikic/php-parser`Required for closure export and name-resolution semantics.---

Installation
------------

[](#installation)

```
composer require componenta/var-export
```

---

Quick start
-----------

[](#quick-start)

```
use Componenta\VarExport\Export;

// Any value — returns executable PHP code
Export::var(['host' => 'localhost', 'port' => 5432]);
// → ['host' => 'localhost', 'port' => 5432]

// Pretty layout (multi-line + trailing comma)
Export::pretty([1, 2, 3]);
// → [
//       1,
//       2,
//       3,
//   ]

// Closures — namespace-aware
$handler = static fn(int $x): int => $x * 2;
Export::closure($handler);
// → static fn(int $x): int => $x * 2

// For file output — appends the semicolon
Export::toFile(['env' => 'prod']);
// → ['env' => 'prod'];
```

Round-trip works through `eval()` (and any PHP source file):

```
$code = Export::var($original);
$restored = eval("return {$code};");
// $restored === $original
```

---

Configuration
-------------

[](#configuration)

```
use Componenta\VarExport\Config\ExportConfig;
use Componenta\VarExport\Config\ClosureUseMode;
use Componenta\VarExport\Config\FormatterMode;

$config = new ExportConfig(
    mode:           FormatterMode::Pretty,
    indent:         '    ',                 // spaces or tabs
    maxDepth:       64,                     // guards runaway recursion
    sortKeys:       false,                  // sort associative array keys
    trailingComma:  true,                   // add trailing comma in pretty mode
    closureUseMode: ClosureUseMode::Preserve,
);

// Presets
ExportConfig::pretty();   // multi-line + trailing comma
ExportConfig::compact();  // single-line

// Fluent copies (every with* returns a new instance)
$config = ExportConfig::pretty()
    ->withIndent("\t")
    ->withSortKeys();
```

### Reusing an exporter

[](#reusing-an-exporter)

One-off calls go through the static facade. For many exports with the same configuration, instantiate `VarExporter` directly — the parsed-AST cache is reused across calls:

```
use Componenta\VarExport\VarExporter;

$exporter = new VarExporter(ExportConfig::pretty());
$a = $exporter->export($closure1);
$b = $exporter->export($closure2);  // closure1's file AST is cached
```

---

Closure capture modes
---------------------

[](#closure-capture-modes)

### `ClosureUseMode::Preserve` (default)

[](#closureusemodepreserve-default)

Keeps the `use(...)` clause verbatim. The captured variables must exist in the scope where the exported code runs.

```
$multiplier = 2;
$fn = function (int $x) use ($multiplier): int {
    return $x * $multiplier;
};

Export::closure($fn);
// → function (int $x) use ($multiplier): int { return $x * $multiplier; }
```

### `ClosureUseMode::Inline`

[](#closureusemodeinline)

Replaces each `use(...)` variable with its current value, yielding a self-contained closure:

```
$config = new ExportConfig(closureUseMode: ClosureUseMode::Inline);

Export::closure($fn, $config);
// → function (int $x): int { return $x * 2; }
```

Inline mode accepts scalar captures and nested scalar arrays. Captures of objects, resources, nested closures or by-reference variables (`use (&$x)`) are rejected with `ClosureExportException`.

---

Exporting objects
-----------------

[](#exporting-objects)

```
enum Priority: string {
    case Low = 'low';
    case High = 'high';
}

final readonly class Task {
    public function __construct(
        public string $title,
        public Priority $priority,
        public array $tags,
    ) {}
}

Export::var(new Task('Ship', Priority::High, ['core']));
// → new \App\Task('Ship', \App\Priority::High, ['core'])
```

Requirements for readonly-class export:

- Class is marked `readonly`
- Every constructor parameter has a matching `public` property

`ObjectExporter::supports($object)` reports up front whether a given object satisfies these rules — use it to pre-flight untrusted input.

---

Helper functions
----------------

[](#helper-functions)

For callers that prefer free functions over static methods:

```
use function Componenta\VarExport\var_export_string;
use function Componenta\VarExport\var_export_pretty;
use function Componenta\VarExport\array_export;
use function Componenta\VarExport\closure_export;

var_export_string($value);
var_export_string($value, pretty: true);
var_export_pretty($value);
array_export([1, 2, 3]);
closure_export(fn() => 42);
```

---

Error handling
--------------

[](#error-handling)

```
use Componenta\VarExport\Exception\{
    ExportException,
    ArrayExportException,
    ClosureExportException,
    ConfigurationException,
};

try {
    $code = Export::var($data);
} catch (ArrayExportException $e) {
    // Max depth, unexportable element, key path context in $e->context
} catch (ClosureExportException $e) {
    // Bound $this, inline captures not supported, ambiguous location
} catch (ConfigurationException $e) {
    // Invalid indent / maxDepth in ExportConfig
} catch (ExportException $e) {
    // Unsupported top-level type
}
```

Every exception carries a `$context` array with metadata (class, key path, variable names, file/line) — values that caused the failure are **not** stored, so logs stay safe.

---

Not supported
-------------

[](#not-supported)

- Mutable objects (non-readonly, or with private state that cannot be reconstructed through the constructor)
- Resources (including stream/curl handles)
- Closures bound to `$this` — convert to `static function() { ... }` before export
- Closures defined in `eval()`'d code (no source file to parse)
- Two or more closures on the same line with identical signatures (ambiguous — keep them on separate lines)

---

License
-------

[](#license)

MIT

###  Health Score

42

—

FairBetter than 88% of packages

Maintenance91

Actively maintained with recent releases

Popularity7

Limited adoption so far

Community13

Small or concentrated contributor base

Maturity51

Maturing project, gaining track record

 Bus Factor1

Top contributor holds 100% of commits — single point of failure

How is this calculated?**Maintenance (25%)** — Last commit recency, latest release date, and issue-to-star ratio. Uses a 2-year decay window.

**Popularity (30%)** — Total and monthly downloads, GitHub stars, and forks. Logarithmic scaling prevents top-heavy scores.

**Community (15%)** — Contributors, dependents, forks, watchers, and maintainers. Measures real ecosystem engagement.

**Maturity (30%)** — Project age, version count, PHP version support, and release stability.

###  Release Activity

Cadence

Unknown

Total

1

Last Release

43d ago

### Community

Maintainers

![](https://avatars.githubusercontent.com/u/20490712?v=4)[Andrey Shelamkoff](/maintainers/Shelamkoff)[@Shelamkoff](https://github.com/Shelamkoff)

---

Top Contributors

[![Shelamkoff](https://avatars.githubusercontent.com/u/20490712?v=4)](https://github.com/Shelamkoff "Shelamkoff (1 commits)")

---

Tags

arrayexportvar\_exportserializationclosurecode-generation

###  Code Quality

TestsPHPUnit

### Embed Badge

![Health badge](/badges/componenta-var-export/health.svg)

```
[![Health](https://phpackages.com/badges/componenta-var-export/health.svg)](https://phpackages.com/packages/componenta-var-export)
```

###  Alternatives

[psalm/plugin-laravel

Psalm plugin for Laravel

3345.3M348](/packages/psalm-plugin-laravel)[tempest/framework

The PHP framework that gets out of your way.

2.2k34.4k17](/packages/tempest-framework)[v.chetkov/php-clean-architecture

PHP Clean Architecture

14661.3k](/packages/vchetkov-php-clean-architecture)[brianhenryie/strauss

Prefixes dependencies namespaces so they are unique to your plugin

192438.1k39](/packages/brianhenryie-strauss)[boundwize/structarmed

Configurable PHP architecture guards — define your layers and rules, then keep them enforced

45629.2k27](/packages/boundwize-structarmed)[typo3/cms-install

TYPO3 CMS Install Tool - The Install Tool is used for installation, upgrade, system administration and setup tasks.

1812.3M510](/packages/typo3-cms-install)

PHPackages © 2026

[Directory](/)[Categories](/categories)[Trending](/trending)[Changelog](/changelog)[Analyze](/analyze)
