PHP'de dizi yapılarını bildirmek

Feb 20 2023
Ne yazık ki, açık dizi türlerini Java gibi diğer programlama dillerinin yaptığı gibi tanımlamak mümkün değildir: Umarım, PHPStan veya Psalm gibi bazı araçlar kodu statik olarak analiz etmemize yardımcı olur, yani yürütmezler ancak kodu temel alan tutarsızlıklar için kontrol ederler. PHP yorumlarında. Bir PHP dizisindeki öğelerin türünü tanımlamanın 3 farklı yolu vardır: Bu, belirli bir türden öğelerin listesini tanımlamanın moda bir yoludur, sorun belirsiz hale gelmesidir ve bu tür bir listeyi kullanan istemciler, olup olmadığını bilemezler. anahtarlar tamsayılar, değişkenler veya dizelerdir.

Ne yazık ki, açık dizi türlerini Java gibi diğer programlama dillerinin yaptığı gibi tanımlamak mümkün değildir:

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

Umarım, PHPStan veya Psalm gibi bazı araçlar, kodu statik olarak analiz etmemize yardımcı olur, yani yürütmezler, PHP yorumlarına dayalı tutarsızlıklar için kodu kontrol ederler.

Bir PHP dizisindeki öğelerin türünü tanımlamanın 3 farklı yolu vardır:

  1. Eski yol:User[]
  2. Liste Şekli: array<int,mixed>&list<mixed>
  3. Nesne Şekli:array{0:int, foo:?string, bar:mixed}

Bu, belirli bir türdeki öğelerin bir listesini tanımlamanın moda bir yoludur, sorun şu ki, belirsiz hale geliyor ve bu tür bir listeyi kullanan istemciler, anahtarların tamsayı mı, kayan nokta mı yoksa dize mi olduğunu bilemezler.
Ayrıca, yanlış türde bir öğeyi anahtarla almaya çalışırsanız statik analizörler başarısız olmaz, bu senaryolarda array<int,mixed>.

Sonunda, daha açık, daha iyi.

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

Aynı türde bir dizi öğeye sahip olduğumuzda listeleri kullanırız. Bunu yapmak için, anahtarın türlerini ve değeri bildirmek için elmas sözdizimini
kullanırız : . Anahtar otomatik artımlı bir tamsayı olduğunda çok kullanışlı bir kısayol vardır: .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);

Dizi bir nesneler koleksiyonu değil de bilgileri tutan bir harita olduğunda nesne şeklini kullanırız. Bunu yapmak için, süslü parantez sözdizimini
kullanırız ve anahtar adını ve türünü tanımlarız, birden çok öğe varsa virgülle ayırabiliriz: . 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;
}

Elbette PHP'deki herhangi bir karmaşık dizi yapısını bu PHP yorumlarıyla temsil etmek mümkündür. Örnek:

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

Kaynaklar:

  • Mezmur | Dizi Şekilleri
  • PHPStan | PHPDoc Türleri