(CJP) # PHP 8.1 でネイティブ サポート!
この投稿では、PHP 8.1 の組み込み列挙型についてすべて読むことができます。 PHP 8.1 より前の列挙型のユーザーランド実装に関する詳細情報をお探しの場合は、引き続きこの記事をお読みください。
PHP での enum の実装を探してここに来た場合は、このようになります。 その背後にあるデザイン哲学に興味がある場合は、読み進めてください!
列挙型、略して「enum」は、名前付きの値を分類するためのデータ型です。 ハードコードされた文字列の代わりに列挙型を使用して、たとえばブログ投稿のステータスを構造化および型指定された方法で表すことができます。
PHP にはネイティブの列挙型がありません。 これは非常に基本的な SPL の実装を提供しますが、これは本当に必要なことではありません。
によって書かれた人気のあるパッケージがあります マチュー・ナポリ
myclabs/php-enum と呼ばれます。 これは、私や他の多くの人が数え切れないほどのプロジェクトで使用しているパッケージです。 それは本当に素晴らしいです。
今日は、ユーザーランドで列挙型などの問題を解決する際に遭遇する問題のいくつかを探りたいと思います。 列挙型に対する私の個人的な見解について話し、コア サポートについて熟考します。
最後に 1 つ: 列挙型とは何かを理解し、実際のプロジェクトで列挙型を使用する方法を知っていることを前提としています。
tpyoに気づきましたか? PR を送信して修正することができます。 このブログの最新情報を知りたい場合は、私をフォローしてください。 ツイッター または私のニュースレターを購読してください:
# 想像してみてください:
PHPでこのようなものを書くことができます…
class Post
public function setStatus(PostStatus $status): void
$this->status = $status;
…そして、 Post::$status 常に次の 3 つの文字列のいずれかです。
draft、 published また archived.
これを保存するとしましょう Post データベースでは、そのステータスは自動的に文字列として表されます。
の myclabs/php-enum パッケージを使用すると、次のように記述できます。
class PostStatus extends Enum
const DRAFT = ‘draft’;
const PUBLISHED = ‘published’;
const ARCHIVED = ‘archived’;
次のように、定数値を直接使用できます。
class Post
public function setStatus(string $status): void
$this->status = $status;
$post->setStatus(PostStatus::DRAFT);
しかし、これにより、すべての文字列が渡される可能性があるため、適切な型チェックを行うことができなくなります。 Post::setStatus().
より良いアプローチは、ライブラリによって導入された小さな魔法を使用することです。
class PostStatus extends Enum
private const DRAFT = ‘draft’;
private const PUBLISHED = ‘published’;
private const ARCHIVED = ‘archived’;
$post->setStatus(PostStatus::DRAFT());
魔法のメソッドを使う __callStatic() その下に、クラスのオブジェクト PostStatus で構築され、 ‘draft’ その中の価値。
これで、check を入力できます PostStatus
入力が「列挙型」によって定義された 3 つのものの 1 つであることを確認します。
ここに問題があります myclabs/php-enum ただし、パッケージ: に依存することによって __callStatic()、オートコンプリートやリファクタリングなどの静的分析の利点が失われます。

この例でわかるように、IDE は PostsStatus::DRAFT() 方法。
幸いなことに、この問題は docblock 型ヒントで解決できます。
class PostStatus extends Enum
private const DRAFT = ‘draft’;
private const PUBLISHED = ‘published’;
private const ARCHIVED = ‘archived’;
$post->setStatus(PostStatus::DRAFT());
しかし、列挙型の値をリファクタリングするときに問題が発生しています。 名前を変更したいとします DRAFT に NEW:

また、重複したコードを維持しています。定数値と doc ブロックがあります。
この時点で、立ち止まって考える時が来ました。 理想的な世界では、PHP に組み込みの列挙型があります。
enum PostStatus
DRAFT, PUBLISHED, ARCHIVED;
現在はそうではないため、ユーザーランドの実装に行き詰まっています。
ユーザーランドで PHP の型システムを拡張することは、魔法とリフレクションという 2 つのことを意味します。
すでにこれら 2 つの要素に依存している場合は、全力を尽くして生活をできるだけシンプルにしてみませんか?
今日の列挙型の書き方は次のとおりです。
class PostStatus extends Enum
意見がありますよね? ただし、維持するコードが少なくて済み、より多くの利点があります。
私 知る これは理想的な状況とはほど遠いものです。 いつの日か、PHP で列挙型の組み込みサポートが見られるのは素晴らしいことです。 しかし、それまでは、これを行う必要があります。
必要に応じて、ここで私の実装を試すことができます。
それで、列挙型についてどう思いますか? それらをコアPHPに入れたいですか? それについて話しましょう ツイッター!