Nette Command-Line
Eine leichtgewichtige Bibliothek zum Erstellen von Kommandozeilenanwendungen in PHP. Sie verarbeitet Schalter, Optionen und positionelle Argumente und hilft Ihnen, farbige Terminalausgaben mit ANSI-Unterstützung zu erzeugen.
Installation:
composer require nette/command-line
Sie erfordert PHP in der Version 8.2 und unterstützt PHP bis 8.5.
Verarbeitung von Kommandozeilenargumenten
Jedes Konsolenskript muss Argumente wie --verbose, -o output.txt oder schlichte Dateinamen
verarbeiten können. Die Klasse Nette\CommandLine\Parser bietet den schnellsten
Einstieg: Sie schreiben einfach den Hilfetext, und der Parser extrahiert die Definitionen der Optionen selbst daraus:
use Nette\CommandLine\Parser;
$parser = new Parser;
$parser->addFromHelp('
-h, --help Show this help
-v, --verbose Enable verbose mode
-o, --output <file> Output file
-f, --format [type] Output format (default: json)
-I, --include <path>... Include paths
--dry-run Show what would be done
');
$args = $parser->parse();
Das war's. Der Parser erkennt, dass --verbose ein Schalter ist, --output einen Wert verlangt und
--format einen optionalen Wert mit json als Standardwert hat. Ihr Hilfetext bleibt so mit den
tatsächlichen Definitionen der Optionen im Einklang.
Die Methode parse() gibt ein assoziatives Array zurück. Die Schlüssel entsprechen genau den Namen der Optionen,
wie Sie sie definiert haben, einschließlich der Bindestriche:
[
'--help' => true, // oder null, wenn nicht verwendet
'--verbose' => null,
'--output' => 'file.txt', // oder null, wenn nicht verwendet
'--format' => 'json', // Standardwert aus (default: json)
'--include' => ['src', 'lib'],
'--dry-run' => null,
]
Standardmäßig liest parse() aus $_SERVER['argv']. Sie können ein eigenes Array übergeben, was
sich beim Testen anbietet:
$args = $parser->parse(['--verbose', '-o', 'out.txt']);
Syntax des Hilfetexts
Der Parser extrahiert die Definitionen der Optionen nach diesen Regeln aus dem formatierten Hilfetext:
--verbose |
Schalter (ohne Wert) |
-v, --verbose |
Schalter mit kurzem Alias |
--output <file> |
Option mit erforderlichem Wert |
--format [type] |
Option mit optionalem Wert |
(default: json) |
setzt den Standardwert |
<path>... |
wiederholbare Option |
Jede Zeile definiert eine Option. Die Namen der Optionen müssen von der Beschreibung durch mindestens zwei Leerzeichen getrennt sein.
Weitere Konfiguration
Manche Einstellungen lassen sich im Hilfetext nicht ausdrücken. Übergeben Sie sie als Array im zweiten Parameter, wobei der Schlüssel der Name der Option ist:
$parser->addFromHelp('
-c, --config <file> Configuration file
-I, --include <path> Include path
-n, --count <num> Number of iterations
', [
'--config' => [
Parser::RealPath => true,
],
'--include' => [
Parser::Repeatable => true,
],
'--count' => [
Parser::Normalizer => fn($v) => (int) $v,
],
]);
Verfügbare Schlüssel:
Parser::Repeatable |
sammelt mehrere Werte in einem Array |
Parser::RealPath |
prüft, ob die Datei existiert, und wandelt den Pfad in einen absoluten um |
Parser::Normalizer |
Transformationsfunktion fn($value) => ... |
Parser::Default |
Standardwert (dasselbe wie (default: x) im Hilfetext) |
Parser::Enum |
Array erlaubter Werte |
Fluent API
Wenn Sie mehr Kontrolle über die Definitionen der Optionen brauchen, verwenden Sie das Fluent API mit den Methoden
addSwitch(), addOption() und addArgument(). Dieser Ansatz eröffnet Ihnen alle
Möglichkeiten, einschließlich Normalizer, Enums und der genauen Steuerung jedes Parameters:
use Nette\CommandLine\Parser;
$parser = new Parser;
$parser
->addSwitch('--verbose', '-v')
->addOption('--output', '-o')
->addArgument('file');
$args = $parser->parse();
Wie bei addFromHelp() können Sie der Methode parse() zum Testen ein eigenes Array übergeben:
$args = $parser->parse(['--verbose', '-o', 'out.txt', 'input.txt']);
Schalter, Optionen und Argumente
Es gibt drei Arten von Eingaben auf der Kommandozeile:
Schalter sind Flags ohne Wert, etwa --verbose oder -v. Sind sie vorhanden, werden sie als
true ausgewertet, sonst als null:
$parser->addSwitch('--verbose', '-v');
// --verbose → true
// -v → true
// (nicht verwendet) → null
Optionen nehmen Werte entgegen, etwa --output file.txt. Der Wert lässt sich durch ein Leerzeichen oder
durch = trennen:
$parser->addOption('--output', '-o');
// --output file.txt → 'file.txt'
// --output=file.txt → 'file.txt'
// -o file.txt → 'file.txt'
// --output → wirft eine Exception (Wert erforderlich)
// (nicht verwendet) → null
Beachten Sie, dass die Option selbst immer optional ist – wird sie nicht verwendet, kommt null zurück. Wird
sie aber verwendet, ist der Wert standardmäßig erforderlich. Mit optionalValue: true erlauben Sie die Option auch
ohne Wert (sie wird dann als true ausgewertet):
$parser->addOption('--format', '-f', optionalValue: true);
// --format json → 'json'
// --format → true
// (nicht verwendet) → null
Wird dieselbe Option ohne repeatable: true mehrfach verwendet, gewinnt der letzte Wert:
$parser->addOption('--output', '-o');
// -o first.txt -o second.txt → 'second.txt'
Argumente sind positionelle Werte ohne Bindestriche. Standardmäßig sind sie erforderlich. Mit
optional: true machen Sie sie optional:
$parser->addArgument('input');
// script.php file.txt → 'file.txt'
// (nicht verwendet) → wirft eine Exception
$parser->addArgument('output', optional: true);
// (nicht verwendet) → null
$parser->addArgument('output', optional: true, fallback: 'out.txt');
// (nicht verwendet) → 'out.txt'
Mit fallback legen Sie den Wert fest, der verwendet wird, wenn eine optionale Option oder ein optionales Argument
nicht angegeben wird. Bei Optionen mit optionalValue: true gilt: Die Verwendung der Option ohne Wert wird weiterhin
als true ausgewertet, während der Standardwert nur dann greift, wenn die Option überhaupt nicht vorhanden ist:
$parser->addOption('--format', '-f', optionalValue: true, fallback: 'json');
// --format xml → 'xml'
// --format → true (Option ohne Wert verwendet)
// (nicht verwendet) → 'json' (Standardwert)
Argumente können auf der Kommandozeile an beliebiger Stelle stehen – sie müssen nicht erst hinter den Optionen kommen:
// alle diese Schreibweisen sind gleichwertig:
// script.php --verbose input.txt
// script.php input.txt --verbose
Werte mit einem Enum einschränken
Beschränken Sie die akzeptierten Werte auf eine bestimmte Menge:
$parser->addOption('--format', '-f', enum: ['json', 'xml', 'csv']);
// --format yaml → wirft "Value of option --format must be json, or xml, or csv."
Wiederholbare Optionen
Mit repeatable: true sammeln Sie mehrere Werte in einem Array:
$parser->addOption('--include', '-I', repeatable: true);
// -I src -I lib → ['src', 'lib']
// (nicht verwendet) → []
$parser->addArgument('files', optional: true, repeatable: true);
// a.txt b.txt → ['a.txt', 'b.txt']
Werte transformieren
Mit normalizer transformieren Sie den verarbeiteten Wert:
$parser->addOption('--count', normalizer: fn($v) => (int) $v);
// --count 42 → 42 (Integer)
Zum Prüfen eines Dateipfads verwenden Sie das eingebaute normalizeRealPath:
$parser->addOption('--config', normalizer: Parser::normalizeRealPath(...));
// --config app.ini → '/full/path/to/app.ini'
// --config missing.ini → wirft "File path 'missing.ini' not found."
Kombination beider Ansätze
Wenn Sie Normalizer nur für einige Optionen brauchen, können Sie addFromHelp() mit den Fluent-Methoden
kombinieren:
$parser
->addFromHelp('
-v, --verbose Enable verbose mode
-q, --quiet Suppress output
')
->addOption('--config', '-c', normalizer: Parser::normalizeRealPath(...))
->addArgument('input');
Fehlerbehandlung
Der Parser wirft bei ungültiger Eingabe \Exception:
use Nette\CommandLine\Parser;
$parser = new Parser;
$parser
->addOption('--output', '-o')
->addArgument('file');
try {
$args = $parser->parse();
} catch (\Exception $e) {
fwrite(STDERR, "Error: {$e->getMessage()}\n");
exit(1);
}
Häufige Fehlermeldungen:
Option --output requires argument. |
Option ohne den erforderlichen Wert verwendet |
Unknown option --foo. |
unbekannte Option |
Missing required argument <file>. |
erforderliches Argument nicht angegeben |
Unexpected parameter foo. |
überzähliges positionelles Argument |
Value of option --format must be json, or xml. |
Wert nicht im Enum |
Mit der Methode isEmpty() stellen Sie fest, ob überhaupt keine Argumente auf der Kommandozeile angegeben wurden
(der Benutzer also nur script.php ohne irgendetwas dahinter aufgerufen hat):
if ($parser->isEmpty()) {
$parser->help();
exit;
}
Umgang mit –help und –version
Wenn Ihr Skript erforderliche Argumente hat, würde der Aufruf script.php --help normalerweise fehlschlagen, weil
das erforderliche Argument fehlt. Verwenden Sie parseOnly(), um die informativen Optionen zuerst zu prüfen:
$parser = new Parser;
$parser
->addSwitch('--help', '-h')
->addSwitch('--version', '-V')
->addArgument('input'); // erforderlich
// Zuerst prüfen wir die informativen Optionen (ohne Validierung, ohne Exceptions)
$info = $parser->parseOnly(['--help', '--version']);
if ($info['--help']) {
$parser->help();
exit;
}
if ($info['--version']) {
echo "1.0.0\n";
exit;
}
// Erst jetzt die vollständige Verarbeitung mit Validierung
$args = $parser->parse();
Die Methode parseOnly():
- verarbeitet nur die angegebenen Optionen und ignoriert alles Übrige,
- respektiert Aliase (
-h→--help), - wirft niemals eine Exception,
- gibt
nullfür Optionen zurück, die nicht verwendet wurden.
Farbige Ausgabe
Die Klasse Nette\CommandLine\Console umhüllt den Text mit ANSI-Farbcodes, sodass Ihre Ausgabe im Terminal hervorsticht:
use Nette\CommandLine\Console;
$console = new Console;
echo $console->color('red', 'Error!') . "\n";
echo $console->color('white/blue', 'White text on blue background') . "\n";
Die Farbe wird als 'Vordergrund' oder 'Vordergrund/Hintergrund' angegeben. Verfügbare Farben sind:
black, gray, silver, white, navy, blue,
green, lime, teal, aqua, maroon, red,
purple, fuchsia, olive und yellow.
Farben werden nur dann automatisch eingeschaltet, wenn die Ausgabe sie unterstützt. Die Methode color() gibt bei
abgeschalteten Farben einen einfachen String zurück, ihr Aufruf ist also immer sicher. Sie können das Verhalten auch von Hand
festlegen:
$console->useColors(false); // schaltet die Farben ab
$console->useColors(true); // erzwingt die Farben
Erkennung des Terminals
Zwei statische Methoden helfen Ihnen bei der Entscheidung, ob Sie Funktionen nutzen, die nur im Terminal Sinn ergeben.
detectColors() gibt false zurück, wenn die Umgebungsvariable NO_COLOR gesetzt ist oder wenn die Ausgabe kein Konsolenterminal ist; die Variable
FORCE_COLOR überstimmt die Prüfung des Terminals:
if (Console::detectColors()) {
// das Terminal unterstützt ANSI-Farben
}
detectTerminal() sagt Ihnen, ob die Ausgabe ein interaktives Terminal (ein TTY) ist. Das eignet sich zum
automatischen Abschalten von Funktionen, die nur in einem Terminal Sinn ergeben, etwa Fortschrittsanzeigen, das Überschreiben von
Zeilen oder interaktive Rückfragen:
if (Console::detectTerminal()) {
// die Ausgabe geht an ein interaktives Terminal, nicht in eine Datei oder Pipe
}
Vollständiges Beispiel
Hier ist ein Skript zur Dateikonvertierung aus der Praxis, das Parser und Console kombiniert:
#!/usr/bin/env php
<?php
use Nette\CommandLine\Parser;
require __DIR__ . '/vendor/autoload.php';
$parser = new Parser;
$parser
->addFromHelp('
-h, --help Show this help
-v, --verbose Show detailed output
-n, --dry-run Show what would be done
-f, --format [type] Output format (default: json)
-o, --output <file> Output file
', [
'--format' => [
Parser::Enum => ['json', 'xml', 'csv'],
],
])
->addArgument('input', normalizer: Parser::normalizeRealPath(...));
// --help noch vor der Validierung behandeln (vermeidet den Fehler "missing argument")
if ($parser->isEmpty() || $parser->parseOnly(['--help'])['--help']) {
echo "Usage: convert [options] <input>\n\n";
$parser->help();
exit;
}
try {
$args = $parser->parse();
} catch (\Exception $e) {
fwrite(STDERR, "Error: {$e->getMessage()}\n");
exit(1);
}
if ($args['--verbose']) {
echo "Converting {$args['input']} to {$args['--format']}...\n";
}
if ($args['--dry-run']) {
echo "Dry run: no changes made.\n";
exit;
}
// ... hier folgt die Logik der Konvertierung ...
echo "Done!\n";
Das Skript akzeptiert Befehle wie:
convert input.txt– Konvertierung mit den Standardeinstellungenconvert -v --format xml input.txt– ausführliche Ausgabe, Format XMLconvert -o result.txt input.txt– Angabe der Ausgabedateiconvert --help– Anzeige der Hilfe (funktioniert auch ohne Eingabedatei)