Array-Strukturen in PHP deklarieren

Feb 20 2023
Leider ist es nicht möglich, explizite Array-Typen zu definieren, wie dies bei anderen Programmiersprachen wie Java der Fall ist: Hoffentlich helfen uns einige Tools wie PHPStan oder Psalm dabei, den Code statisch zu analysieren, was bedeutet, dass sie den Code nicht ausführen, sondern auf Inkonsistenzen überprüfen zu PHP-Kommentaren. Es gibt drei verschiedene Möglichkeiten, den Typ von Elementen in einem PHP-Array zu definieren: Dies ist eine modische Methode, um eine Liste von Elementen eines bestimmten Typs zu definieren. Das Problem besteht darin, dass sie mehrdeutig wird und Clients, die diese Art von Liste verwenden, nicht wissen können, ob Schlüssel sind Ganzzahlen, Gleitkommazahlen oder Zeichenfolgen.

Leider ist es nicht möglich, explizite Array-Typen zu definieren, wie dies bei anderen Programmiersprachen wie Java der Fall ist:

List<User> users = new ArrayList<>();

Hoffentlich helfen uns einige Tools wie PHPStan oder Psalm dabei, den Code statisch zu analysieren, was bedeutet, dass sie den Code nicht ausführen, sondern anhand von PHP-Kommentaren auf Inkonsistenzen überprüfen.

Es gibt drei verschiedene Möglichkeiten, die Art der Elemente in einem PHP-Array zu definieren:

  1. Legacy-Weg:User[]
  2. Listenform: array<int,mixed>&list<mixed>
  3. Objektform:array{0:int, foo:?string, bar:mixed}

Dies ist eine modische Methode zum Definieren einer Liste von Elementen eines bestimmten Typs. Das Problem besteht darin, dass sie mehrdeutig wird und Clients, die diese Art von Liste verwenden, nicht wissen können, ob es sich bei Schlüsseln um Ganzzahlen, Gleitkommazahlen oder Zeichenfolgen handelt.
Außerdem scheitern statische Analysatoren nicht, wenn Sie versuchen, ein Element über einen Schlüssel mit einem falschen Typ abzurufen. In diesen Szenarien würde ich die Verwendung empfehlen array<int,mixed>.

Letztendlich gilt: Je expliziter, desto besser.

/** @var User[] $users */
$users = [ ... ];

# Are keys autoincremental integers, random numbers, maybe strings... ?
$firstUser = $users[ ? ];

# Static analyzers won't complain if you use an incorrect type 

Wir verwenden Listen, wenn wir ein Array von Elementen desselben Typs haben.
Dazu verwenden wir die Rautensyntax , um die Typen des Schlüssels und des Werts zu deklarieren: array<int,mixed>. Es gibt eine sehr praktische Verknüpfung, wenn der Schlüssel eine automatisch inkrementelle Ganzzahl ist: list<mixed>.

/** @var array<string,User> $users */
$users = [
    'jesus' => new User('Jesus Valera'),
    'chema' => new User('Chema Valera'),
];

$userJesus = $users['jesus'];
$userChema = $users['chema'];

$users[0]; # ERROR: "Offset 0 does not exist on array<string, User>"

---

/** @var list<User> $users */
$users = [ ... ];

$firstUser = reset($users);
$lastUser = end($users);

Wir verwenden die Objektform, wenn das Array keine Sammlung von Objekten, sondern eine Karte ist, die Informationen enthält.
Dazu verwenden wir die Syntax der geschweiften Klammern und definieren den Schlüsselnamen und den Typ. Bei mehreren Elementen können wir durch Kommas trennen: .array{foo:int, bar:string}

/** @var array{id:int, birthdate: DateTimeImmutable} */
$additionalInfo = [ ... ];

$id = $additionalInfo['id']; # int
$birthdate = $additionalInfo['birthdate']; # DateTimeImmutable

final class User
{
    /** @var list<Comment> */
    public readonly array $comments;

    /** @var array{id:int, birthdate: DateTimeImmutable} */
    public readonly array $additionalInfo;
}

Natürlich ist es mit diesen PHP-Kommentaren möglich, jede komplexe Array-Struktur in PHP darzustellen. Beispiel:

/**
 * @var list<
 *   array{
 *     uuid?: string,
 *     content: array{name: string, foo: ?stdClass},
 *   }
 * > $array
 */
$array = [
    0 => [
        'uuid' => 'XXXX-XXX-XXX-XXXX',
        'content' => [
            'name' => 'str',
            'foo' => null,
        ],
    ],
    1 => [
        'content' => [
            'name' => 'str',
            'foo' => new stdClass(),
        ],
    ],
    // ...
];

Ressourcen:

  • Psalm | Array-Formen
  • PHPStan | PHPDoc-Typen