このライブラリの使用は、特に新しいプロジェクトでは推奨されなくなりました。 PHP 8.1 は列挙型をネイティブにサポートします。
#332を参照してください。
Laravel 用のシンプルで拡張可能かつ強力な列挙型の実装。
クラス定数としてのキー値ペアの列挙
フル機能を備えた一連のメソッド
列挙型のインスタンス化
フラグ付き/ビットごとの列挙型
タイプヒンティング
属性キャスト
Enum 職人ジェネレーター
enum キーまたは値を入力パラメータとして渡すための検証ルール
ローカリゼーションのサポート
マクロ経由で拡張可能
作成者: ベン・サンプソン
ガイド
インストール
ネイティブ PHP 列挙型への移行
Enum ライブラリ
基本的な使い方
列挙型の定義
インスタンス化
インスタンスのプロパティ
インスタンスキャスト
インスタンスの平等性
タイプヒント
フラグ付き/ビットごとの列挙型
属性のキャスト
移行
検証
ローカリゼーション
説明のカスタマイズ
クラスの説明のカスタマイズ
値の説明のカスタマイズ
Enum 基本クラスの拡張
Laravel Novaの統合
PHPStanの統合
職人コマンド一覧
Enum クラスのリファレンス
スタブ
あなたは6.x
のドキュメントを読んでいます。
Laravel 8 を使用している場合は、 4.x
のドキュメントを参照してください。
Laravel 7 を使用している場合は、 2.x
のドキュメントを参照してください。
Laravel 6以下を使用している場合は、 1.x
のドキュメントを参照してください。
最新バージョンへのアップグレード方法については、アップグレード ガイドを参照してください。
laravel-enum の使用についてブログ投稿を書きました: https://sampo.co.uk/blog/using-enums-in-laravel
PHP 8、およびLaravel 9または10が必要です。
作曲家にはbensampo/laravel-enumが必要です
PHP 8.1 は列挙型をネイティブにサポートします。次の手順を使用して、 BenSampoEnumEnum
の使用状況をネイティブ PHP 列挙型に移行できます。
次の要件を満たしていることを確認してください。
PHP 8.1以降
Laravel 10以降
Rector 0.17 以降、 rector.php
には関連ファイルがすべて含まれています
このライブラリの最新バージョン
プロジェクトのサイズに応じて、すべての列挙型を一度に移行するか、一度に 2 つまたは 1 つの列挙型だけを移行するかを選択できます。
すべての列挙型を一度に変換します: php artisan enum:to-native
変換を制限するには、列挙型の完全修飾クラス名を渡します: php artisan enum:to-native "AppEnumsUserType"
これは、Laravel のブートストラップ フェーズ中に enum が使用され、その使用法の変換が Larastan に干渉し、Rector の 2 回目の実行が機能しなくなる場合に必要です。
見逃したエッジケースのコード変更を確認して検証します。
「未実装」を参照
Enum::coerce()
: 値のみが渡された場合は、それをtryFrom()
に置き換えることができます。キーまたはインスタンスも渡すことができる場合は、これをカバーする追加のロジックが必要になる可能性があります。
Enum::$description
およびEnum::getDescription()
: 代替手段を実装します。
BenSampoEnumExceptionsInvalidEnumKeyException
またはBenSampoEnumExceptionsInvalidEnumMemberException
を処理する try/catch ブロック。ネイティブ列挙型によってスローされたValueError
キャッチするか、 tryFrom()
使用に切り替えてnull
を処理します。
すべての列挙型が変換されたら、このライブラリへの依存関係を削除できます。
一般的に使用されるコミュニティ提供の列挙型のリストを参照してダウンロードします。
列挙型ライブラリ →
次のアーティザン コマンドを使用して、新しい列挙型クラスを生成できます。
php 職人 make:enum UserType
ここで、列挙型が定数として持つことができる値を追加するだけです。
<?php destroy(strict_types=1);namespace AppEnums;use BenSampoEnumEnum;final class UserType extends Enum {const Administrator = 0;const Moderator = 1;const Subscriber = 2;const SuperAdministrator = 3; }
それでおしまい! enum 値はプレーン定数として定義されているため、他のクラス定数と同様に簡単にアクセスできることに注意してください。
UserType::Administrator // 値は 0 です
型ヒントの利点を利用して関数間で列挙型を渡すために列挙型をインスタンス化すると便利です。
さらに、無効な値を使用して列挙型をインスタンス化することは不可能であるため、渡された値が常に有効であることを確認できます。
便宜上、列挙型は複数の方法でインスタンス化できます。
// 必要な enum 値をパラメータとして渡す、標準の新しい PHP クラス$enumInstance = new UserType(UserType::Administrator);// コンストラクタと同じ、value によってインスタンス化$enumInstance = UserType::fromValue(UserType::Administrator) ;// 値の代わりに enum キーを使用します$enumInstance = UserType::fromKey('Administrator');// キー名をメソッドとして静的に呼び出します。 __callStatic magic$enumInstance = UserType::Administrator();// 指定されたキーまたは値を使用して新しい Enum のインスタンス化を試みます。 Enum をインスタンス化できない場合は null を返します。$enumInstance = UserType::coerce($someValue);
IDE で静的インスタンス化ヘルパーをオートコンプリートさせたい場合は、artisan コマンドを通じて PHPDoc アノテーションを生成できます。
デフォルトでは、 app/Enums
内のすべての Enum に注釈が付けられます ( --folder
にパスを渡すことでフォルダーを変更できます)。
php 職人の列挙型:注釈を付ける
クラス名を指定することで、単一のクラスにアノテーションを付けることができます。
php 職人 enum:annotate "AppEnumsUserType"
enum インスタンスを取得すると、 key
、 value
、 description
にプロパティとしてアクセスできるようになります。
$userType = UserType::fromValue(UserType::SuperAdministrator);$userType->key; // SuperAdministrator$userType->値; // 3$userType->説明; // スーパー管理者
これは、列挙インスタンスをブレード ビューに渡す場合に特に便利です。
Enum インスタンスは__toString()
マジック メソッドを実装しているため、文字列にキャストできます。
これは、たとえばブレード ビューでエコーできることも意味します。
$userType = UserType::fromValue(UserType::SuperAdministrator); (文字列) $userType // '3'
インスタンスをis
メソッドに渡すことで、任意の値とインスタンスが等しいかどうかをチェックできます。便宜上、 is
メソッドのまったく逆のisNot
メソッドもあります。
$admin = UserType::Administrator();$admin->is(UserType::Administrator); // true$admin->is($admin); // true$admin->is(UserType::Administrator()); // true$admin->is(UserType::Moderator); // false$admin->is(UserType::Moderator()); // false$admin->is('ランダム値'); // 間違い
また、 in
メソッドを使用してインスタンスの値が可能な値の配列と一致するかどうかを確認したり、 notIn
使用してインスタンス値が値の配列に含まれないかどうかを確認したりすることもできます。 Iterable をチェックすることもできます。
$admin = UserType::Administrator();$admin->in([UserType::Moderator, UserType::Administrator]); // true$admin->in([UserType::Moderator(), UserType::Administrator()]); // true$admin->in([UserType::Moderator, UserType::Subscriber]); // false$admin->in(['ランダム値']); // false$admin->notIn([UserType::Moderator, UserType::Administrator]); // false$admin->notIn([UserType::Moderator(), UserType::Administrator()]); // false$admin->notIn([UserType::Moderator, UserType::Subscriber]); // true$admin->notIn(['ランダム値']); // 真実
インスタンス化された列挙型はシングルトンではなく、毎回新しいオブジェクトが作成されます。したがって、異なる enum インスタンスの厳密な比較===
、値に関係なく、常にfalse
を返します。対照的に、緩やかな比較==
値に依存します。
$admin = UserType::Administrator();$admin === UserType::Administrator(); // falseUserType::Administrator() === UserType::Administrator(); // false$admin === UserType::Moderator(); // false$admin === $admin; // true$admin == UserType::Administrator(); // true$admin == UserType::Administrator; // true$admin == UserType::Moderator(); // false$admin == UserType::Moderator; // 間違い
enum インスタンスの利点の 1 つは、次に示すように、タイプ ヒントを使用できることです。
関数 canPerformAction(UserType $userType) {if ($userType->is(UserType::SuperAdministrator)) {true を返す; } false を返します。 }$userType1 = UserType::fromValue(UserType::SuperAdministrator);$userType2 = UserType::fromValue(UserType::Moderator);canPerformAction($userType1); // truecanPerformAction($userType2) を返します。 // falseを返します
標準の列挙型は一度に 1 つの値を表しますが、フラグ付き列挙型またはビットごとの列挙型は複数の値を同時に表すことができます。これは、限られたオプションのセットの複数の選択を表現したい場合に最適です。この好例としては、使用可能な権限の数が限られているものの、ユーザーが権限をまったく持たないか、一部またはすべてを持つことができるユーザー権限が挙げられます。
次の職人コマンドを使用して、フラグ付き列挙型を作成できます。
php artisan make:enum UserPermissions --flagged
値を定義するときは 2 の累乗を使用する必要があります。これを行う最も簡単な方法は、次のように左シフト<<
演算子を使用することです。
最終クラス UserPermissions は FlaggedEnum を拡張します {const ReadComments = 1 << 0;const WriteComments = 1 << 1;const EditComments = 1 << 2;const DeleteComments = 1 << 3;// 次は `1 << 4` などとなります。 ..}
ビット単位または|
使用できます。指定された値のセットを表すショートカット値を設定します。
最終クラス UserPermissions は FlaggedEnum を拡張します {const ReadComments = 1 << 0;const WriteComments = 1 << 1;const EditComments = 1 << 2;const DeleteComments = 1 << 3;// Shortcutsconst Member = self::ReadComments | self::WriteComments; // 読み取りと書き込み。const Moderator = self::Member | self::EditComments; // メンバーが持つすべての権限に加え、Edit.const Admin = self::Moderator | self::コメントを削除します。 // モデレーターが持つすべての権限に加えて、削除。}
フラグ付き列挙型をインスタンス化するには、いくつかの方法があります。
// 標準の新しい PHP クラス。必要な enum 値を値の配列または enum インスタンスの配列として渡します$permissions = new UserPermissions([UserPermissions::ReadComments, UserPermissions::EditComments]);$permissions = new UserPermissions([UserPermissions: :ReadComments(), UserPermissions::EditComments()]);// 静的フラグ メソッド、再び値の配列または列挙インスタンスの配列としての必要な列挙値 $permissions = UserPermissions::flags([UserPermissions::ReadComments, UserPermissions::EditComments]);$permissions = UserPermissions::flags([UserPermissions::ReadComments(), UserPermissions::EditComments()]);
属性のキャストは、単一値の列挙型と同じように機能します。
フラグ付き列挙型には値をまったく含めることはできません。フラグ付きのすべての列挙型には、 0
に相当するNone
という事前定義された定数があります。
UserPermissions::flags([])->value === UserPermissions::None; // 真実
標準の列挙型メソッドに加えて、フラグ付き列挙型で使用できる一連の便利なメソッドがあります。
注: 静的プロパティが渡される場所ではどこでも、列挙型インスタンスを渡すこともできます。
列挙型のフラグを指定されたフラグの配列に設定します。
$permissions = UserPermissions::flags([UserPermissions::ReadComments]);$permissions->flags([UserPermissions::EditComments, UserPermissions::DeleteComments]); // フラグは EditComments、DeleteComments になりました。
指定されたフラグを列挙型に追加します
$permissions = UserPermissions::flags([UserPermissions::ReadComments]);$permissions->addFlag(UserPermissions::EditComments); // フラグは ReadComments、EditComments になりました。
指定されたフラグを列挙型に追加します
$permissions = UserPermissions::flags([UserPermissions::ReadComments]);$permissions->addFlags([UserPermissions::EditComments, UserPermissions::WriteComments]); // フラグは ReadComments、EditComments、WriteComments になりました。
すべてのフラグを列挙型に追加します
$permissions = UserPermissions::flags([UserPermissions::ReadComments]);$permissions->addAllFlags(); // Enum にすべてのフラグが設定されました
指定されたフラグを列挙型から削除します
$permissions = UserPermissions::flags([UserPermissions::ReadComments, UserPermissions::WriteComments]);$permissions->removeFlag(UserPermissions::ReadComments); // フラグは WriteComments になりました。
指定されたフラグを列挙型から削除します
$permissions = UserPermissions::flags([UserPermissions::ReadComments, UserPermissions::WriteComments, UserPermissions::EditComments]);$permissions->removeFlags([UserPermissions::ReadComments, UserPermissions::WriteComments]); // フラグは EditComments になりました。
列挙型からすべてのフラグを削除します
$permissions = UserPermissions::flags([UserPermissions::ReadComments, UserPermissions::WriteComments]);$permissions->removeAllFlags();
列挙型に指定されたフラグがあるかどうかを確認します。
$permissions = UserPermissions::flags([UserPermissions::ReadComments, UserPermissions::WriteComments]);$permissions->hasFlag(UserPermissions::ReadComments); // True$permissions->hasFlag(UserPermissions::EditComments); // 間違い
列挙型に指定されたすべてのフラグがあるかどうかを確認します。
$permissions = UserPermissions::flags([UserPermissions::ReadComments, UserPermissions::WriteComments]);$permissions->hasFlags([UserPermissions::ReadComments, UserPermissions::WriteComments]); // True$permissions->hasFlags([UserPermissions::ReadComments, UserPermissions::EditComments]); // 間違い
列挙型に指定されたフラグがないかどうかを確認します。
$permissions = UserPermissions::flags([UserPermissions::ReadComments, UserPermissions::WriteComments]);$permissions->notHasFlag(UserPermissions::EditComments); // True$permissions->notHasFlag(UserPermissions::ReadComments); // 間違い
列挙型に指定されたフラグがないかどうかを確認してください。
$permissions = UserPermissions::flags([UserPermissions::ReadComments, UserPermissions::WriteComments]);$permissions->notHasFlags([UserPermissions::ReadComments, UserPermissions::EditComments]); // True$permissions->notHasFlags([UserPermissions::ReadComments, UserPermissions::WriteComments]); // 間違い
フラグをインスタンスの配列として返します。
$permissions = UserPermissions::flags([UserPermissions::ReadComments, UserPermissions::WriteComments]);$permissions->getFlags(); // [UserPermissions::ReadComments(), UserPermissions::WriteComments()];
列挙型に複数のフラグが設定されているかどうかを確認します。
$permissions = UserPermissions::flags([UserPermissions::ReadComments, UserPermissions::WriteComments]);$permissions->hasMultipleFlags(); // True;$permissions->removeFlag(UserPermissions::ReadComments)->hasMultipleFlags(); // 間違い
列挙型のビットマスクを取得します。
UserPermissions::Member()->getBitmask(); // 11;UserPermissions::Moderator()->getBitmask(); // 111;UserPermissions::Admin()->getBitmask(); // 1111;UserPermissions::DeleteComments()->getBitmask(); // 1000;
Eloquent クエリでフラグ付き列挙型を直接使用するには、次のメソッドを提供するQueriesFlaggedEnums
トレイトをモデルで使用できます。
User::hasFlag('権限', UserPermissions::DeleteComments())->get();
User::notHasFlag('権限', UserPermissions::DeleteComments())->get();
User::hasAllFlags('permissions', [UserPermissions::EditComment(), UserPermissions::ReadComment()])->get();
User::hasAnyFlags('permissions', [UserPermissions::DeleteComments(), UserPermissions::EditComments()])->get();
Laravel の組み込みカスタム キャストを使用して、モデル属性を列挙型にキャストできます。これにより、取得時に属性が enum インスタンスにキャストされ、設定時に enum 値に戻されます。 Enum::class
Castable
コントラクトを実装しているため、列挙型のクラス名を指定するだけで済みます。
BenSampoEnumTestsEnumsUserType を使用します;IlluminateDatabaseEloquentModel を使用します;クラスの例は Model を拡張します {protected $casts = ['random_flag' => 'boolean', // 標準laravelの例 Cast'user_type' => UserType::class, // enumキャストの例]; }
ここで、 Example
モデルのuser_type
属性にアクセスすると、基になる値がUserType
列挙型として返されます。
$example = Example::first();$example->user_type // UserType のインスタンス
属性キャストを最大限に活用するには、列挙型インスタンスで使用できるメソッドとプロパティを確認してください。
enum 値または別の enum インスタンスを渡すことによって、値を設定できます。
$example = Example::first();// enum valueを使用して設定$example->user_type = UserType::Moderator;// enumを使用して設定instance$example->user_type = UserType::Moderator();
$model->toArray()
動作のカスタマイズtoArray
使用するとき (またはコントローラーから応答としてモデルを返すとき)、Laravel は enum インスタンスのtoArray
メソッドを呼び出します。
デフォルトでは、これはネイティブ型の値のみを返します。たとえば、JavaScript アプリに戻るなど、他のプロパティ (キー、説明) にもアクセスしたい場合があります。
この動作をカスタマイズするには、enum インスタンスのtoArray
メソッドをオーバーライドします。
// 例 Enumfinal クラス UserType extends Enum {const ADMINISTRATOR = 0;const MODERATOR = 1; }$instance = UserType::Moderator();// デフォルトのパブリック関数 toArray() {$this->値を返す; }// int(1) を返します// すべてのプロパティを返しますpublic function toArray() {$this を返す; }// すべてのプロパティの配列を返します// array(3) {// ["value"]=>// int(1)"// ["key"]=>// string(9) "MODERATOR "// ["説明"]=>// string(9) "モデレーター"// }
多くのデータベースは、すべてを文字列として返します (たとえば、整数が文字列'1'
として返される場合があります)。ライブラリのユーザーの負担を軽減するために、型強制を使用して目的の値を把握します。これを制御したい場合は、enum クラスのparseDatabase
静的メソッドをオーバーライドできます。
最終クラス UserType は Enum を拡張します {const Administrator = 0;const Moderator = 1;パブリック静的関数 parseDatabase($value) {return (int) $value; } }
parseDatabase
メソッドからnull
を返すと、モデルの属性もnull
になります。これは、データベースにNULL
代わりに空の文字列など、一貫性のない空白値が格納されている場合に便利です。
モデルの属性を列挙型にキャストしている場合は、laravel-ide-helper パッケージを使用してプロパティ docblock を自動的に生成できます。
enum はコード レベルで一貫性を強制するため、データベース レベルで一貫性を再度行う必要はありません。そのため、データベース列の推奨される型は enum 値に応じてstring
またはint
です。これは、データベース層を気にせずにコード内の列挙値を追加/削除できることを意味します。
AppEnumsUserType を使用する;IlluminateSupportFacadesSchema を使用する;IlluminateDatabaseSchemaBlueprint を使用する;IlluminateDatabaseMigrationsMigration を使用する;クラス CreateUsersTable は Migration を拡張します {/** * 移行を実行します。 * * @return void */public function up(): void{ Schema::table('users', function (Blueprint $table): void {$table->bigIncrements('id');$table->timestamps();$table->string('type') ->default(UserType::Moderator); }); } }
enum
列型の使用あるいは、移行でEnum
クラスを使用して enum 列を定義することもできます。 enum 値は文字列として定義する必要があります。
AppEnumsUserType を使用する;IlluminateSupportFacadesSchema を使用する;IlluminateDatabaseSchemaBlueprint を使用する;IlluminateDatabaseMigrationsMigration を使用する;クラス CreateUsersTable は Migration を拡張します {/** * 移行を実行します。 * * @return void */public function up(): void{ Schema::table('users', function (Blueprint $table): void {$table->bigIncrements('id');$table->timestamps();$table->enum('type', UserType:: getValues()) ->default(UserType::Moderator); }); } }
EnumValue
ルールを使用すると、コントローラーに渡された列挙値が特定の列挙型の有効な値であることを検証できます。
BenSampoEnumRulesEnumValue を使用;パブリック関数ストア(Request $request) {$this->validate($request, ['user_type' => ['required', new EnumValue(UserType::class)], ]); }
デフォルトでは、型チェックは厳密に設定されていますが、EnumValue クラスのオプションの 2 番目のパラメータにfalse
渡すことで、これを回避できます。
new EnumValue(UserType::class, false) // 厳密な型チェックをオフにします。
EnumKey
ルールを使用してキーを検証することもできます。これは、たとえば並べ替えやフィルター処理の URL パラメーターとして enum キーを使用する場合に便利です。
BenSampoEnumRulesEnumKey を使用;パブリック関数ストア(Request $request) {$this->validate($request, ['user_type' => ['required', new <span class="pl-v"