nette/neon
Human-friendly configuration format for PHP. NEON is a structured data language similar to YAML/JSON, with neat syntax for arrays and objects, comments, and multiline strings. Includes fast parser and emitter, used across Nette and beyond.
Installation:
composer require nette/neon
Ensure PHP 8.2+ is used (v3.4.8+ requirement).
First Use Case: Decode a NEON file into a PHP array:
use Nette\Neon\Neon;
$config = Neon::decodeFile(__DIR__.'/config.neon');
// Example config.neon:
// services:
// mail:
// driver: smtp
// host: mail.example.com
Encode Data Back to NEON:
$neonString = Neon::encode([
'services' => [
'mail' => [
'driver' => 'smtp',
'host' => 'mail.example.com',
],
],
]);
Key Files:
vendor/nette/neon/src/ for core classes.vendor/nette/neon/tests/ for edge-case examples.Configuration Loading:
config() helper for non-JSON/YAML configs:
$config = Neon::decodeFile(config_path('app.neon'));
config(['app' => $config['app']]);
Neon::decodeFile() for atomic reads (avoids race conditions in deployments).Dynamic Configuration:
config():
$neonData = Neon::decode($request->input('config_neon'));
config(['feature_flags' => array_merge(config('feature_flags'), $neonData)]);
Validation & Linting:
use Nette\Neon\Linter;
$errors = Linter::lintFile(__DIR__.'/config.neon');
if (!empty($errors)) {
throw new \RuntimeException("NEON lint errors: " . implode("\n", $errors));
}
Service Container Integration:
$this->app->singleton('config.neon', function () {
return Neon::decodeFile(config_path('services.neon'));
});
config/services.neon) and JSON/YAML for API-driven configs.$cachedConfig = cache()->remember('neon-config', now()->addHour(), function () {
return Neon::decodeFile(config_path('app.neon'));
});
Neon::decode() in try-catch for malformed NEON:
try {
$data = Neon::decode($neonString);
} catch (\Nette\Neon\Exception $e) {
report($e);
return response()->json(['error' => 'Invalid NEON'], 400);
}
""" syntax for SQL queries or long text:
queries:
create_table: """
CREATE TABLE users (
id INT AUTO_INCREMENT PRIMARY KEY,
name VARCHAR(255)
)
"""
UTF-8 Strictness:
if (!mb_check_encoding($neonString, 'UTF-8')) {
throw new \InvalidArgumentException('NEON must be UTF-8 encoded');
}
PHP 8.2+ Requirement:
Breaking Changes:
on/off syntax and \x** literals. Update legacy NEON files:
# Before (deprecated)
enabled: on
hex_value: \xFF
# After
enabled: true
hex_value: 0xFF
Big Integers:
PHP_INT_MAX are decoded as strings (v3.4.3). Handle with:
$value = Neon::decode($neonString);
if (is_string($value) && ctype_digit($value)) {
$value = gmp_init($value); // Use GMP for large integers
}
Circular References:
serialize()/unserialize() for complex objects.Indentation Sensitivity:
# Correct
services:
mail:
driver: smtp
# Incorrect (mixed tabs/spaces)
services:
mail:
driver: smtp
Linting Errors:
php -r "(new Nette\Neon\Linter)->lintFile('config.neon');"
AST Inspection:
Traverser to debug complex NEON structures:
use Nette\Neon\Neon;
use Nette\Neon\Traverser;
$ast = Neon::parse($neonString);
$traverser = new Traverser();
$traverser->onEnterNode(function ($node) {
dump(get_class($node), $node->getName());
});
$traverser->traverse($ast);
Encoding Quirks:
\n, \t) are escaped in output. Use raw strings for multiline:
# Multiline string (preserves newlines)
description: """
This is a
multiline string.
"""
Performance:
Neon::decodeFile() with a stream wrapper:
$data = Neon::decodeFile('php://temp', function () {
yield file_get_contents('large-config.neon');
});
Custom Node Types:
Nette\Neon\Node\Node to support domain-specific syntax:
class LaravelNode extends Node {
public function getLaravelValue(): mixed { ... }
}
Encoder Flags:
$neon = Neon::encode($data, Neon::BLOCK_ARRAY, Neon::INDENT_4_SPACES);
Traverser Callbacks:
$traverser = new Traverser();
$traverser->onEnterNode(function (Node $node) {
if ($node instanceof ArrayNode) {
$node->setIndentation(2); // Force 2-space indent
}
});
$traverser->traverse($ast);
Linter Rules:
Nette\Neon\Linter:
class CustomLinter extends Linter {
protected function checkCustomRules(Node $node): void {
// Implement custom validation logic
}
}
How can I help you explore Laravel packages today?