Start · Sprachen · PHP · Referenz · PhpToken

PhpToken

Klasse

Objektorientierte Alternative zu <code>token_get_all()</code>, die alle Tokens einheitlich als Objekte mit Typ, Wert und Positionsinformationen repräsentiert.

seit PHP 8.0.0 Kategorie: misc

Signatur

class PhpToken implements Stringable

Beschreibung

PhpToken wurde in PHP 8.0 eingeführt und bietet eine modernere, objektorientierte Schnittstelle zur PHP-Tokenisierung. Während token_get_all() ein gemischtes Array aus Arrays und Strings zurückgibt (einfache Tokens wie ; werden als Plain-String geliefert), normalisiert PhpToken jeden Token zu einem einheitlichen Objekt mit den Eigenschaften id, text, line und pos.

Die statische Methode PhpToken::tokenize() ist der Haupteinstiegspunkt. Sie gibt ein Array von PhpToken-Objekten zurück. Typische Anwendungsfälle sind statische Code-Analyse, Refactoring-Werkzeuge, Linter, Code-Formatter oder jede Anwendung, die PHP-Quellcode programmatisch inspizieren oder transformieren muss.

Ein besonders nützliches Feature ist die Methode is(), mit der geprüft werden kann, ob ein Token einem bestimmten Typ oder Text entspricht. Das vereinfacht die Analyse erheblich gegenüber dem manuellen Vergleich mit Token-Konstanten. Über isIgnorable() lassen sich Whitespace-, Kommentar- und andere unwichtige Tokens schnell herausfiltern.

PhpToken ist erweiterbar: Eigene Unterklassen können überschriebene Methoden und zusätzliche Eigenschaften hinzufügen; tokenize() gibt dann Instanzen der abgeleiteten Klasse zurück, wenn es in der Unterklasse aufgerufen wird.

Parameter

Name Typ Default Beschreibung
$id Pflicht int Die Token-ID, entweder eine der T_*-Konstanten für bekannte Tokens oder der ASCII-Wert des Zeichens für einfache Ein-Zeichen-Tokens (z. B. ord(';')).
$text Pflicht string Der tatsächliche Quellcode-Text dieses Tokens, z. B. 'function', '$foo' oder ';'.
$line int -1 Die Zeilennummer (1-basiert), in der dieses Token im Quellcode beginnt.
$pos int -1 Der Byte-Offset (0-basiert) vom Beginn des Quellcodes, an dem dieses Token beginnt.

Beispiele

Alle Funktionsnamen aus einer PHP-Datei extrahieren

<?php
$code = <<<'PHP'
<?php
function hello(string $name): void {
    echo "Hello, $name!";
}
function world(): string {
    return 'world';
}
PHP;

$tokens = PhpToken::tokenize($code);

$functionNames = [];
foreach ($tokens as $i => $token) {
    if ($token->is(T_FUNCTION)) {
        // Nächsten nicht-ignorierbaren Token suchen (= Funktionsname)
        for ($j = $i + 1; $j < count($tokens); $j++) {
            if (!$tokens[$j]->isIgnorable()) {
                if ($tokens[$j]->is(T_STRING)) {
                    $functionNames[] = $tokens[$j]->text;
                }
                break;
            }
        }
    }
}

print_r($functionNames);
Array ( [0] => hello [1] => world )

Token-Details inspizieren und is()-Methode nutzen

<?php
$code = '<?php $x = 42;';

$tokens = PhpToken::tokenize($code);

foreach ($tokens as $token) {
    if ($token->isIgnorable()) {
        continue; // Whitespace und Kommentare überspringen
    }
    printf(
        "ID: %-6d | Text: %-15s | Zeile: %d | Pos: %d\n",
        $token->id,
        json_encode($token->text),
        $token->line,
        $token->pos
    );
}

// Gezielt nach einem bestimmten Token suchen
$hasEcho = array_filter($tokens, fn(PhpToken $t) => $t->is(T_ECHO));
echo 'Enthält echo: ' . (count($hasEcho) > 0 ? 'ja' : 'nein') . PHP_EOL;

// is() akzeptiert auch Strings für direkten Textvergleich
$hasSemicolon = array_filter($tokens, fn(PhpToken $t) => $t->is(';'));
echo 'Enthält Semikolon: ' . (count($hasSemicolon) > 0 ? 'ja' : 'nein') . PHP_EOL;
ID: 379 | Text: "<?php " | Zeile: 1 | Pos: 0 ID: 320 | Text: "$x" | Zeile: 1 | Pos: 6 ID: 61 | Text: "=" | Zeile: 1 | Pos: 9 ID: 305 | Text: "42" | Zeile: 1 | Pos: 11 ID: 59 | Text: ";" | Zeile: 1 | Pos: 13 Enthält echo: nein Enthält Semikolon: ja

PhpToken in einer eigenen Unterklasse erweitern

<?php
class EnrichedToken extends PhpToken
{
    public function isKeyword(): bool
    {
        return $this->is([
            T_FUNCTION, T_CLASS, T_INTERFACE, T_TRAIT,
            T_IF, T_ELSE, T_ELSEIF, T_WHILE, T_FOR,
            T_FOREACH, T_RETURN, T_ECHO, T_NEW,
        ]);
    }
}

$code = '<?php function foo() { return new stdClass(); }';

// tokenize() gibt EnrichedToken-Instanzen zurück
$tokens = EnrichedToken::tokenize($code);

foreach ($tokens as $token) {
    if ($token->isKeyword()) {
        echo "Schlüsselwort gefunden: '{$token->text}' in Zeile {$token->line}" . PHP_EOL;
    }
}
Schlüsselwort gefunden: 'function' in Zeile 1 Schlüsselwort gefunden: 'return' in Zeile 1 Schlüsselwort gefunden: 'new' in Zeile 1

// Wichtig · Fallstricke

Statische Methode tokenize(): Der eigentliche Einstiegspunkt ist PhpToken::tokenize(string $code, int $flags = 0): static[]. Der Parameter $flags akzeptiert TOKEN_PARSE, analog zu token_get_all().

Methoden der Instanz:

  • is(int|string|array $kind): bool — prüft den Typ oder Text; Arrays ermöglichen Mehrfachvergleiche.
  • isIgnorable(): bool — gibt true zurück für Whitespace (T_WHITESPACE), Kommentare (T_COMMENT, T_DOC_COMMENT) und das öffnende Tag (T_OPEN_TAG).
  • getTokenName(): ?string — gibt den symbolischen Namen der Token-Konstante zurück, z. B. 'T_FUNCTION'.
  • __toString(): string — gibt text zurück; die Klasse implementiert Stringable.

Sicherheitshinweis: PhpToken::tokenize() führt keinen Code aus – es wird nur das Lexing durchgeführt. Dennoch sollte ungeprüfter Benutzer-Input nicht unbegrenzt an diese Methode übergeben werden, da sehr langer Code zu hohem Speicherverbrauch führen kann.

Vererbung: Wird tokenize() in einer Unterklasse aufgerufen (z. B. MyToken::tokenize($code)), sind alle zurückgegebenen Objekte Instanzen der Unterklasse – Late Static Binding wird unterstützt.