К сожалению, невозможно определить явные типы массивов, как это делают другие языки программирования, такие как Java:

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

Было несколько попыток добиться этого, одна из последних была сделана Никитой Поповым в этом pull request, к сожалению, вывод о текущем статусе PHP был невозможен, это потребуется переписать огромное количество кода, и некоторые из них очень важны.

Будем надеяться, что некоторые инструменты, такие как PHPStan или Psalm, помогают нам анализировать код статически, то есть они не выполняют, а проверяют код на несоответствия на основе комментариев PHP.

Существует 3 разных способа определить тип элементов массива PHP:

  1. Устаревший способ: User[]
  2. Форма списка: array<int,mixed> и list<mixed>
  3. Форма объекта: array{0:int, foo:?string, bar:mixed}

Наследие

Это модный способ определить список элементов определенного типа, но проблема в том, что он становится неоднозначным, и клиенты, использующие такой список, не могут знать, являются ли ключи целыми числами, числами с плавающей запятой или строками.< br /> Также статические анализаторы не дадут сбой, если вы попытаетесь получить элемент по ключу с неправильным типом, в этих сценариях я бы предложил использовать array<int,mixed>.

В конце концов, чем откровеннее, тем лучше.

/** @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 🤕

Форма списка

Мы используем списки, когда у нас есть массив элементов одного типа.
Для этого мы используем алмазный синтаксис для объявления типов ключа и значения: array<int,mixed>. Есть очень удобный ярлык, когда ключ является автоматически увеличивающимся целым числом: 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);

Форма объекта

Мы используем форму объекта, когда массив представляет собой не набор объектов, а карту, которая содержит информацию.
Для этого мы используем фигурные синтаксис квадратных скобок и определяем имя ключа и тип, мы можем разделить запятыми, если есть несколько элементов: array{foo:int, bar:string}.

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

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

Пример класса User, содержащего два массива: список и форму объекта.

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

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

Использование этих PHP-комментариев дает множество преимуществ: они не только предоставляют разработчикам лучшую обратную связь о форме массива, но и IDE предлагают автозавершение при повторении отдельных элементов!

Конечно, с помощью этих PHP-комментариев можно представить любую сложную структуру массива в PHP. Пример:

/**
 * @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(),
        ],
    ],
    // ...
];

Мы можем использовать комментарии PHP к массивам где угодно (свойства класса, параметры функции, встроенная инициализация…)

Ресурсы: