NEON pro PHP
Balíček nette/neon čte a zapisuje NEON v PHP. Díky němu:
- dekódujete konfigurační soubor do hodnot PHP a hodnoty zakódujete zpět do NEONu
- upravíte soubor tak, že každý komentář a mezera, na které nesáhnete, zůstanou na svém místě
- dáte některým hodnotám vlastní význam, třeba konstantám nebo parametrům
- zkontrolujete soubory pomocí
neon-lintv editoru, v CI nebo po AI agentovi
Instalace
Knihovnu stáhnete a nainstalujete pomocí nástroje Composer:
composer require nette/neon
Vyžaduje PHP 8.4 až 8.6 s rozšířeními json a mbstring.
Dekódování
Dejme tomu, že vaše aplikace má nastavení v souboru config.neon:
# database connection
database:
host: localhost
port: 3306
services:
- App\Model\ArticleFacade
Statická třída Nette\Neon\Neon ho načte do obyčejného pole PHP:
use Nette\Neon\Neon;
$config = Neon::decodeFile('config.neon');
// ['database' => ['host' => 'localhost', 'port' => 3306], 'services' => ['App\Model\ArticleFacade']]
Metoda decode() dělá totéž s řetězcem:
$value = Neon::decode('hello: world'); // ['hello' => 'world']
Hodnoty formátu se převedou na tyto hodnoty PHP:
| NEON | PHP |
|---|---|
null, true, yes … |
null, bool |
| celé číslo | int; nad PHP_INT_MAX řetězec string z jeho číslic |
| desetinné číslo | float |
| řetězec | string |
| datum | DateTimeImmutable |
| entita, řetěz | Nette\Neon\Entity |
| sekvence, mapování | array |
PHP ukládá sekvence i mapování do polí, takže prázdné [] i prázdné {} se stanou
[]. Datum bez časové zóny dostane výchozí časovou zónu PHP.
Kódování
Metoda encode() zapíše hodnotu PHP jako NEON. Ve výchozím stavu zapíše vše na jeden řádek; pokud jako
druhý argument předáte true, dostanete bloky:
Neon::encode(['roles' => ['guest', 'admin']]);
// '{roles: [guest, admin]}'
Neon::encode(['roles' => ['guest', 'admin']], true);
// "roles:\n\t- guest\n\t- admin\n\n"
Místo true můžete předat funkci, která rozhodne u každého pole zvlášť. Dostane pole a seznam klíčů,
které k němu vedou, a pro blok vrátí true. Tahle zapíše bloky jen v první úrovni:
Neon::encode($config, fn($value, $path) => !$path);
// "database: {host: localhost, port: 3306}\nservices: [App\\Model\\ArticleFacade]\n"
Třetí argument určuje odsazení, výchozí je tabulátor. Řetězec dostane uvozovky, jen když je potřebuje, a víceřádkový řetězec se zapíše jako víceřádkový řetězec.
Některé hodnoty jako NEON bez ztráty zapsat nejde: řetězec, který není platné UTF-8, INF a
NAN, resource, closure nebo struktura, která obsahuje sama sebe. Pro ně encode() vyhodí
Nette\Neon\Exception.
Chyby
Když vstup není platný NEON, decode() a decodeFile() vyhodí Nette\Neon\Exception
s pozicí problému:
try {
$config = Neon::decode("database:\n\thost: localhost\n\thost: db");
} catch (Nette\Neon\Exception $e) {
echo $e->getMessage(); // Duplicated key 'host' on line 3 at column 2
echo $e->getDescription(); // Duplicated key 'host'
}
Sloupec se počítá ve znacích, ne v bajtech. Když chybu zobrazujete po svém, třeba u pole formuláře, metoda
getDescription() vrátí hlášku bez pozice.
Vlastní hodnoty: Evaluator
Neon::decode() převádí syntaktický strom na hodnoty pomocí třídy
Nette\Neon\Evaluator. Její potomek může některým hodnotám dát vlastní význam. Tento převádí názvy
konstant PHP na jejich hodnoty:
use Nette\Neon\Evaluator;
use Nette\Neon\Neon;
use Nette\Neon\Nodes\LiteralNode;
use Nette\Neon\Place;
final class ConstantEvaluator extends Evaluator
{
protected function evaluateLiteral(LiteralNode $node, Place $place): mixed
{
$value = parent::evaluateLiteral($node, $place);
return $place === Place::Value && is_string($value) && defined($value)
? constant($value)
: $value;
}
}
$document = Neon::parse('errorLevel: E_ALL');
$config = new ConstantEvaluator()->evaluate($document->value);
// ['errorLevel' => 30719]
Metody, které můžete přepsat, jsou evaluateLiteral(), evaluateString(),
evaluateEntity(), evaluateChain() a evaluateItem(). Place říká, kde hodnota
stojí: jako hodnota, jako klíč, jako jméno entity nebo jako článek řetězu. Díky tomu příklad výše nechá na pokoji
klíč, který se jmenuje jako konstanta. Takto čte svou konfiguraci DI
kontejner Nette.
Kontrola souborů: neon-lint
Balíček obsahuje příkaz neon-lint. Předáte mu soubory nebo adresáře a on vypíše jeden řádek pro
každý problém:
vendor/bin/neon-lint config/
config/local.neon:3:2: Duplicated key 'user'
Když jsou všechny soubory platné, nevypíše nic. V adresáři hledá soubory *.neon a vynechá
vendor, node_modules a skryté adresáře, - čte standardní vstup. Jeho chování mění
tyto volby:
| Volba | Účinek |
|---|---|
--check |
ověří navíc, že se soubor načte zpět bajt po bajtu |
--json |
vypíše nálezy jako JSON, pro nástroje |
--quiet |
nevypíše nic, jen nastaví návratový kód |
--verbose |
vypíše počet souborů, když jsou všechny platné |
Návratový kód je 0, když jsou všechny soubory platné, 1 při nálezu a 2 při chybném volání. Příkaz, jeho výstup i návratové kódy jsou stejné v knihovnách pro JavaScript a Python, takže cokoliv, co ho spouští, funguje se všemi.
Proto se hodí i pro AI agenty: když ho agent spustí po každé změně souboru .neon, dozví se o rozbitém
souboru hned a opraví ho dřív, než pokračuje. Pluginy Nette pro AI agenty to dělají
za vás.
Co dál
- Formát NEON – syntaxe formátu
- Úpravy souborů – změna souboru se zachováním formátování a syntaktický strom
- Upgrade – co se změnilo ve verzi 4.0