A TOML (v1.0 and v1.1) parser and encoder for PHP with AST access and collected parse errors.
- Strict validation for malformed keys, tables, strings, numbers, and datetimes
- Error recovery with multiple error collection for tooling workflows
- Clean architecture with separate Lexer, Parser, and AST
- Zero required extensions (optional php-ds for performance)
- AST access for analysis or editor integrations
- Explicit local date/time/datetime value objects for encoding
- PHP 8.2 or higher
composer require php-collective/toml- Interactive Playground - Full-featured sandbox with all options.
use PhpCollective\Toml\Toml;
// Decode TOML to PHP array
$config = Toml::decode(<<<'TOML'
[database]
host = "localhost"
port = 5432
TOML);
echo $config['database']['host']; // "localhost"
// Encode PHP array to TOML
$toml = Toml::encode([
'server' => [
'host' => '0.0.0.0',
'port' => 8080,
],
]);// Decode string - throws ParseException on error
$array = Toml::decode($tomlString);
// Decode file
$array = Toml::decodeFile('/path/to/config.toml');
// Parse without throwing - for tooling
$result = Toml::tryParse($tomlString);
if ($result->isValid()) {
$array = $result->getValue();
} else {
foreach ($result->getErrors() as $error) {
echo $error->format($tomlString);
}
}
// Parse to AST for analysis
$document = Toml::parse($tomlString);
// Parse without exceptions and keep diagnostics + partial AST
$result = Toml::tryParse($tomlString);
$document = $result->getDocument();use PhpCollective\Toml\Encoder\DocumentFormattingMode;
use PhpCollective\Toml\Encoder\EncoderOptions;
use PhpCollective\Toml\Ast\Value\StringStyle;
use PhpCollective\Toml\Ast\Value\StringValue;
// Encode to TOML string
$toml = Toml::encode($array);
// Encode directly to file
Toml::encodeFile('/path/to/config.toml', $array);
// With options - e.g. omit nulls instead of throwing
$toml = Toml::encode($array, new EncoderOptions(skipNulls: true));
// encodeDocument() is normalized by default
$document = Toml::parse($tomlString, true);
$toml = Toml::encodeDocument($document);
// Encode document directly to file
Toml::encodeDocumentFile('/path/to/output.toml', $document);
// Opt into source-aware formatting for minimal-diff AST re-encoding
$document = Toml::parse($tomlString, true);
$document->items[0]->value = new StringValue('new value');
$toml = Toml::encodeDocument(
$document,
new EncoderOptions(documentFormatting: DocumentFormattingMode::SourceAware),
);DocumentFormattingMode::SourceAware is lossless for unchanged parsed regions and uses local fallback rules for edited ones. See the Compatibility page for the exact editing contract.
skipNulls lets encode() omit nulls instead of throwing.
The parser provides detailed error messages:
Parse error: unterminated string
3 | name = "value
| ^
4 | other = 123
Hint: Did you forget to close the string with "?
For tooling, use tryParse() to collect all errors:
$result = Toml::tryParse($input);
foreach ($result->getErrors() as $error) {
// $error->message - Error description
// $error->span - Position (line, column, offset)
// $error->hint - Optional suggestion
}The library currently supports:
- All string types (basic, literal, multi-line)
- Integers (decimal, hex, octal, binary)
- Floats (including inf, nan)
- Booleans
- Dates and times (offset, local datetime, local date, local time)
- Arrays (including multiline arrays and trailing commas)
- Inline tables (single-line only; trailing commas rejected)
- Tables and array of tables
- Dotted keys
See the Support Matrix for current coverage and known gaps.
For explicit local temporal encoding, use:
PhpCollective\Toml\Value\LocalDatePhpCollective\Toml\Value\LocalTimePhpCollective\Toml\Value\LocalDateTime
| Feature | php-collective/toml | Others |
|---|---|---|
| Support matrix | Yes | Varies |
| Error Recovery | Yes | No |
| Multiple Errors | Yes | No |
| AST Access | Yes | Limited/No |
| Round-trip formatting preservation | Partial | Varies |
| PHP 8.2+ Features | Yes | Varies |
See Limitations for details.