L'utilisation de cette bibliothèque n'est plus recommandée, notamment pour les nouveaux projets. PHP 8.1 prend en charge les énumérations de manière native.
Voir #332.
Implémentation d'énumération simple, extensible et puissante pour Laravel.
Énumérer les paires clé-valeur en tant que constantes de classe
Suite complète de méthodes
Instanciation d'énumération
Énumérations marquées/au niveau du bit
Indice de saisie
Castation d'attributs
Générateur d'artisans Enum
Règles de validation pour transmettre une clé ou des valeurs d'énumération en tant que paramètres d'entrée
Prise en charge de la localisation
Extensible via des macros
Créé par Ben Sampson
Guide
Installation
Migrer vers les énumérations PHP natives
Bibliothèque d'énumération
Utilisation de base
Définition de l'énumération
Instanciation
Propriétés de l'instance
Création d'instances
Égalité des instances
Indice de saisie
Énumération marquée/au niveau du bit
Casting d'attributs
Migrations
Validation
Localisation
Personnalisation des descriptions
Personnalisation de la description de la classe
Personnalisation des descriptions de valeurs
Extension de la classe de base Enum
Intégration de Laravel Nova
Intégration PHPStan
Liste des commandes artisanales
Référence de classe Enum
Talons
Vous lisez la documentation de 6.x
.
Si vous utilisez Laravel 8, veuillez consulter la documentation de 4.x
Si vous utilisez Laravel 7, veuillez consulter la documentation de 2.x
Si vous utilisez Laravel 6 ou une version antérieure, veuillez consulter la documentation de 1.x
.
Veuillez consulter le guide de mise à niveau pour plus d'informations sur la mise à niveau vers la dernière version.
J'ai écrit un article de blog sur l'utilisation de laravel-enum : https://sampo.co.uk/blog/using-enums-in-laravel
Nécessite PHP 8 et Laravel 9 ou 10.
le compositeur nécessite bensampo/laravel-enum
PHP 8.1 prend en charge les énumérations de manière native. Vous pouvez migrer vos utilisations de BenSampoEnumEnum
vers des énumérations PHP natives en suivant les étapes suivantes.
Assurez-vous de remplir les conditions suivantes :
PHP 8.1 ou supérieur
Laravel 10 ou supérieur
Rector 0.17 ou supérieur, votre rector.php
inclut tous les fichiers pertinents
Dernière version de cette bibliothèque
En fonction de la taille de votre projet, vous pouvez choisir de migrer toutes les énumérations en même temps, ou de migrer seulement quelques ou une énumération à la fois.
Convertir toutes les énumérations à la fois : php artisan enum:to-native
Passez le nom de classe complet d'une énumération pour limiter la conversion : php artisan enum:to-native "AppEnumsUserType"
Ceci est nécessaire si des énumérations sont utilisées pendant la phase d'amorçage de Laravel, la conversion de leurs utilisations interfère avec Larastan et empêche une deuxième exécution de Rector de fonctionner.
Examinez et validez les modifications de code pour les cas extrêmes manqués :
Voir Non implémenté
Enum::coerce()
: Si seules des valeurs ont été transmises, vous pouvez les remplacer par tryFrom()
. Si des clés ou des instances peuvent également être transmises, vous aurez peut-être besoin d'une logique supplémentaire pour couvrir cela.
Enum::$description
et Enum::getDescription()
: implémentez une alternative.
try/catch-blocks qui gèrent BenSampoEnumExceptionsInvalidEnumKeyException
ou BenSampoEnumExceptionsInvalidEnumMemberException
. Soit captez l' ValueError
lancée par les énumérations natives, soit passez à l'utilisation tryFrom()
et gérez null
.
Une fois toutes les énumérations converties, vous pouvez supprimer votre dépendance sur cette bibliothèque.
Parcourez et téléchargez à partir d’une liste d’énumérations couramment utilisées et fournies par la communauté.
Bibliothèque d'énumération →
Vous pouvez utiliser la commande Artisan suivante pour générer une nouvelle classe enum :
php artisan make: enum Type d'utilisateur
Il ne vous reste plus qu'à ajouter les valeurs possibles que votre énumération peut avoir comme constantes.
<?php declare(strict_types=1);namespace AppEnums;use BenSampoEnumEnum;final class UserType extends Enum {const Administrateur = 0 ; const Modérateur = 1 ; const Abonné = 2 ; const SuperAdministrateur = 3 ; }
C'est ça! Notez que, comme les valeurs d'énumération sont définies comme des constantes simples, vous pouvez simplement y accéder comme n'importe quelle autre constante de classe.
UserType :: Administrateur // A une valeur de 0
Il peut être utile d'instancier des énumérations afin de les transmettre entre fonctions avec l'avantage de l'indication de type.
De plus, il est impossible d'instancier une énumération avec une valeur non valide, vous pouvez donc être certain que la valeur transmise est toujours valide.
Pour plus de commodité, les énumérations peuvent être instanciées de plusieurs manières :
// Nouvelle classe PHP standard, passant la valeur enum souhaitée en paramètre$enumInstance = new UserType(UserType::Administrator);// Identique au constructeur, instancié par valeur$enumInstance = UserType::fromValue(UserType::Administrator) ;// Utiliser une clé enum au lieu de sa valeur$enumInstance = UserType::fromKey('Administrator');// Appeler statiquement le nom de la clé en tant que méthode, en utilisant __callStatic magic$enumInstance = UserType::Administrator();// Tentative d'instancier un nouvel Enum en utilisant la clé ou la valeur donnée. Renvoie null si l'Enum ne peut pas être instancié.$enumInstance = UserType::coerce($someValue);
Si vous souhaitez que votre IDE complète automatiquement les assistants d'instanciation statiques, vous pouvez générer des annotations PHPDoc via une commande artisanale.
Par défaut, tous les Enums dans app/Enums
seront annotés (vous pouvez changer de dossier en passant un chemin vers --folder
).
php artisan enum: annoter
Vous pouvez annoter une seule classe en spécifiant le nom de la classe.
php artisan enum: annoter "AppEnumsUserType"
Une fois que vous avez une instance enum, vous pouvez accéder à la key
, value
et description
en tant que propriétés.
$userType = UserType::fromValue(UserType::SuperAdministrator);$userType->key; // SuperAdministrateur$userType->valeur ; // 3$userType->description; // Super administrateur
Ceci est particulièrement utile si vous transmettez une instance d'énumération à une vue lame.
Les instances Enum peuvent être converties en chaînes lorsqu'elles implémentent la méthode magique __toString()
.
Cela signifie également qu'ils peuvent être repris dans les vues de lame, par exemple.
$userType = UserType::fromValue(UserType::SuperAdministrator); (chaîne) $userType // '3'
Vous pouvez vérifier l'égalité d'une instance par rapport à n'importe quelle valeur en la transmettant à la méthode is
. Pour plus de commodité, il existe également une méthode isNot
qui est exactement l’inverse de la méthode is
.
$admin = UserType::Administrateur();$admin->is(UserType::Administrateur); // vrai$admin->est($admin); // true$admin->is(UserType::Administrator()); // true$admin->is(UserType::Moderator); // false$admin->is(UserType::Moderator()); // false$admin->is('valeur-random'); // FAUX
Vous pouvez également vérifier si la valeur de l'instance correspond à un tableau de valeurs possibles à l'aide de la méthode in
et utiliser notIn
pour vérifier si la valeur de l'instance ne se trouve pas dans un tableau de valeurs. Les itérables peuvent également être vérifiés.
$admin = UserType::Administrateur();$admin->in([UserType::Moderator, UserType::Administrateur]); // true$admin->in([UserType::Moderator(), UserType::Administrator()]); // true$admin->in([UserType::Moderator, UserType::Subscriber]); // false$admin->in(['valeur-random']); // false$admin->notIn([UserType::Moderator, UserType::Administrator]); // false$admin->notIn([UserType::Moderator(), UserType::Administrator()]); // false$admin->notIn([UserType::Moderator, UserType::Subscriber]); // true$admin->notIn(['valeur-random']); // vrai
Les énumérations instanciées ne sont pas des singletons, mais un nouvel objet est créé à chaque fois. Ainsi, une comparaison stricte ===
de différentes instances d'énumération renverra toujours false
, quelle que soit la valeur. En revanche, une comparaison lâche ==
dépendra de la valeur.
$admin = UserType::Administrateur();$admin === UserType::Administrateur(); // falseUserType::Administrateur() === UserType::Administrateur(); // false$admin === UserType::Moderator(); // faux$admin === $admin; // true$admin == UserType::Administrateur(); // true$admin == UserType :: Administrateur ; // true$admin == UserType::Moderator(); // false$admin == UserType::Moderator; // FAUX
L'un des avantages des instances enum est qu'elles vous permettent d'utiliser des indications de type, comme indiqué ci-dessous.
fonction canPerformAction (UserType $userType) {if ($userType->is(UserType::SuperAdministrator)) {return true ; }retourne faux ; }$userType1 = UserType::fromValue(UserType::SuperAdministrator);$userType2 = UserType::fromValue(UserType::Moderator);canPerformAction($userType1); // Renvoie truecanPerformAction($userType2); // Renvoie faux
Les énumérations standard représentent une seule valeur à la fois, mais les énumérations marquées ou au niveau du bit sont capables de représenter plusieurs valeurs simultanément. Cela les rend parfaits lorsque vous souhaitez exprimer plusieurs sélections d’un ensemble limité d’options. Un bon exemple de ceci serait les autorisations utilisateur où il existe un nombre limité d'autorisations possibles mais où un utilisateur peut en avoir aucune, certaines ou la totalité.
Vous pouvez créer une énumération marquée à l'aide de la commande artisanale suivante :
php artisan make:enum UserPermissions --flagged
Lorsque vous définissez des valeurs, vous devez utiliser des puissances de 2, le moyen le plus simple de le faire est d'utiliser l'opérateur Shift Left <<
comme ceci :
La classe finale UserPermissions étend FlaggedEnum {const ReadComments = 1 << 0;const WriteComments = 1 << 1;const EditComments = 1 << 2;const DeleteComments = 1 << 3;// Le suivant serait `1 << 4` et ainsi de suite. ..}
Vous pouvez utiliser le bitwise ou |
pour définir une valeur de raccourci qui représente un ensemble donné de valeurs.
La classe finale UserPermissions étend FlaggedEnum {const ReadComments = 1 << 0;const WriteComments = 1 << 1;const EditComments = 1 << 2;const DeleteComments = 1 << 3;// Shortcutsconst Member = self::ReadComments | self::WriteComments; // Lecture et écriture.const Moderator = self::Member | self::EditComments; // Toutes les autorisations dont dispose un membre, plus Edit.const Admin = self::Moderator | self::DeleteComments; // Toutes les autorisations dont dispose un modérateur, plus Supprimer.}
Il existe plusieurs façons d'instancier une énumération marquée :
// Nouvelle classe PHP standard, transmettant les valeurs d'énumération souhaitées sous forme de tableau de valeurs ou d'instances d'énumération$permissions = new UserPermissions([UserPermissions::ReadComments, UserPermissions::EditComments]);$permissions = new UserPermissions([UserPermissions: :ReadComments(), UserPermissions::EditComments()]);// Méthode des indicateurs statiques, en passant à nouveau les valeurs d'énumération souhaitées sous forme de tableau de valeurs ou de tableau de enum instances$permissions = UserPermissions::flags([UserPermissions::ReadComments, UserPermissions::EditComments]);$permissions = UserPermissions::flags([UserPermissions::ReadComments(), UserPermissions::EditComments()]);
La conversion d'attributs fonctionne de la même manière que les énumérations à valeur unique.
Les énumérations marquées ne peuvent contenir aucune valeur. Chaque énumération signalée a une constante prédéfinie de None
qui est comparable à 0
.
UserPermissions::flags([])->value === UserPermissions::None; // Vrai
En plus des méthodes d'énumération standard, il existe une suite de méthodes utiles disponibles sur les énumérations signalées.
Remarque : partout où une propriété statique est transmise, vous pouvez également transmettre une instance d'énumération.
Définissez les indicateurs de l'énumération sur le tableau d'indicateurs donné.
$permissions = UserPermissions::flags([UserPermissions::ReadComments]);$permissions->flags([UserPermissions::EditComments, UserPermissions::DeleteComments]); // Les indicateurs sont désormais : EditComments, DeleteComments.
Ajouter le drapeau donné à l'énumération
$permissions = UserPermissions::flags([UserPermissions::ReadComments]);$permissions->addFlag(UserPermissions::EditComments); // Les indicateurs sont désormais : ReadComments, EditComments.
Ajouter les drapeaux donnés à l'énumération
$permissions = UserPermissions::flags([UserPermissions::ReadComments]);$permissions->addFlags([UserPermissions::EditComments, UserPermissions::WriteComments]); // Les indicateurs sont désormais : ReadComments, EditComments, WriteComments.
Ajouter tous les drapeaux à l'énumération
$permissions = UserPermissions::flags([UserPermissions::ReadComments]);$permissions->addAllFlags(); // Enum a maintenant tous les drapeaux
Supprimer l'indicateur donné de l'énumération
$permissions = UserPermissions::flags([UserPermissions::ReadComments, UserPermissions::WriteComments]);$permissions->removeFlag(UserPermissions::ReadComments); // Les indicateurs sont désormais : WriteComments.
Supprimer les indicateurs donnés de l'énumération
$permissions = UserPermissions::flags([UserPermissions::ReadComments, UserPermissions::WriteComments, UserPermissions::EditComments]);$permissions->removeFlags([UserPermissions::ReadComments, UserPermissions::WriteComments]); // Les indicateurs sont désormais : EditComments.
Supprimer tous les indicateurs de l'énumération
$permissions = UserPermissions::flags([UserPermissions::ReadComments, UserPermissions::WriteComments]);$permissions->removeAllFlags();
Vérifiez si l'énumération a l'indicateur spécifié.
$permissions = UserPermissions::flags([UserPermissions::ReadComments, UserPermissions::WriteComments]);$permissions->hasFlag(UserPermissions::ReadComments); // True$permissions->hasFlag(UserPermissions::EditComments); // FAUX
Vérifiez si l'énumération contient tous les indicateurs spécifiés.
$permissions = UserPermissions::flags([UserPermissions::ReadComments, UserPermissions::WriteComments]);$permissions->hasFlags([UserPermissions::ReadComments, UserPermissions::WriteComments]); // True$permissions->hasFlags([UserPermissions::ReadComments, UserPermissions::EditComments]); // FAUX
Vérifiez si l'énumération n'a pas l'indicateur spécifié.
$permissions = UserPermissions::flags([UserPermissions::ReadComments, UserPermissions::WriteComments]);$permissions->notHasFlag(UserPermissions::EditComments); // True$permissions->notHasFlag(UserPermissions::ReadComments); // FAUX
Vérifiez si l'énumération ne contient aucun des indicateurs spécifiés.
$permissions = UserPermissions::flags([UserPermissions::ReadComments, UserPermissions::WriteComments]);$permissions->notHasFlags([UserPermissions::ReadComments, UserPermissions::EditComments]); // True$permissions->notHasFlags([UserPermissions::ReadComments, UserPermissions::WriteComments]); // FAUX
Renvoie les indicateurs sous forme de tableau d'instances.
$permissions = UserPermissions::flags([UserPermissions::ReadComments, UserPermissions::WriteComments]);$permissions->getFlags(); // [UserPermissions::ReadComments(), UserPermissions::WriteComments()];
Vérifiez s'il y a plusieurs indicateurs définis sur l'énumération.
$permissions = UserPermissions::flags([UserPermissions::ReadComments, UserPermissions::WriteComments]);$permissions->hasMultipleFlags(); // True;$permissions->removeFlag(UserPermissions::ReadComments)->hasMultipleFlags(); // FAUX
Obtenez le masque de bits pour l'énumération.
UserPermissions::Member()->getBitmask(); // 11;UserPermissions::Moderator()->getBitmask(); // 111;UserPermissions::Admin()->getBitmask(); // 1111;UserPermissions::DeleteComments()->getBitmask(); // 1000 ;
Pour utiliser des énumérations marquées directement dans vos requêtes Eloquent, vous pouvez utiliser le trait QueriesFlaggedEnums
sur votre modèle qui vous fournit les méthodes suivantes :
User::hasFlag('permissions', UserPermissions::DeleteComments())->get();
User::notHasFlag('permissions', UserPermissions::DeleteComments())->get();
User::hasAllFlags('permissions', [UserPermissions::EditComment(), UserPermissions::ReadComment()])->get();
User::hasAnyFlags('permissions', [UserPermissions::DeleteComments(), UserPermissions::EditComments()])->get();
Vous pouvez convertir les attributs du modèle en énumérations à l'aide de la conversion personnalisée intégrée de Laravel. Cela convertira l'attribut en une instance d'énumération lors de l'obtention et reviendra à la valeur d'énumération lors de la définition. Puisque Enum::class
implémente le contrat Castable
, il vous suffit de spécifier le nom de classe de l'énumération :
utiliser BenSampoEnumTestsEnumsUserType; utiliser IlluminateDatabaseEloquentModel; l'exemple de classe étend le modèle {protected $casts = ['random_flag' => 'boolean', // Exemple standard laravel cast'user_type' => UserType::class, // Exemple de cast enum]; }
Désormais, lorsque vous accédez à l'attribut user_type
de votre Example
de modèle, la valeur sous-jacente sera renvoyée sous forme d'énumération UserType
.
$example = Exemple::first();$example->user_type // Instance de UserType
Passez en revue les méthodes et propriétés disponibles sur les instances d'énumération pour tirer le meilleur parti de la conversion d'attributs.
Vous pouvez définir la valeur en transmettant la valeur enum ou une autre instance enum.
$example = Exemple::first();// Définir à l'aide de la valeur enum$example->user_type = UserType::Moderator;//Définir à l'aide de l'instance enum$example->user_type = UserType::Moderator();
$model->toArray()
Lorsque vous utilisez toArray
(ou renvoyez un ou plusieurs modèles de votre contrôleur en réponse), Laravel appellera la méthode toArray
sur l'instance enum.
Par défaut, cela renverra uniquement la valeur dans son type natif. Vous souhaiterez peut-être également avoir accès aux autres propriétés (clé, description), par exemple pour revenir à l'application javascript.
Pour personnaliser ce comportement, vous pouvez remplacer la méthode toArray
sur l'instance enum.
// Exemple de classe Enumfinal UserType étend Enum {const ADMINISTRATEUR = 0;const MODÉRATEUR = 1; }$instance = UserType::Moderator();// Fonction publique par défaut toArray() {return $this->valeur ; }// Renvoie int(1)// Renvoie toutes les fonctions publiques de propriétés àArray() {return $this; }// Renvoie un tableau de toutes les propriétés// array(3) {// ["value"]=>// int(1)"// ["key"]=>// string(9) "MODERATOR "// ["description"]=>// string(9) "Modérateur"// }
De nombreuses bases de données renvoient tout sous forme de chaînes (par exemple, un entier peut être renvoyé sous forme de chaîne '1'
). Pour réduire les frictions pour les utilisateurs de la bibliothèque, nous utilisons la coercition de type pour déterminer la valeur souhaitée. Si vous préférez contrôler cela, vous pouvez remplacer la méthode statique parseDatabase
sur votre classe enum :
la classe finale UserType étend Enum {const Administrateur = 0 ; const Modérateur = 1 ; fonction statique publique parseDatabase ($value) {return (int) $valeur ; } }
Le renvoi de null
à partir de la méthode parseDatabase
entraînera que l'attribut du modèle soit également null
. Cela peut être utile si votre base de données stocke des valeurs vides incohérentes telles que des chaînes vides au lieu de NULL
.
Si vous convertissez les attributs de votre modèle en énumérations, le package laravel-ide-helper peut être utilisé pour générer automatiquement des docblocks de propriétés pour vous.
Étant donné que les énumérations assurent la cohérence au niveau du code, il n'est pas nécessaire de le faire à nouveau au niveau de la base de données. Par conséquent, le type recommandé pour les colonnes de la base de données est string
ou int
en fonction de vos valeurs d'énumération. Cela signifie que vous pouvez ajouter/supprimer des valeurs d'énumération dans votre code sans vous soucier de votre couche de base de données.
utiliser AppEnumsUserType ; utiliser IlluminateSupportFacadesSchema ; utiliser IlluminateDatabaseSchemaBlueprint ; utiliser IlluminateDatabaseMigrationsMigration ; la classe CreateUsersTable étend la migration {/** * Exécutez les migrations. * * @return void */public function up(): void{ Schema::table('users', fonction (Blueprint $table) : void {$table->bigIncrements('id');$table->timestamps();$table->string('type') ->par défaut (UserType :: Modérateur); }); } }
enum
Vous pouvez également utiliser des classes Enum
dans vos migrations pour définir des colonnes d'énumération. Les valeurs d'énumération doivent être définies sous forme de chaînes.
utiliser AppEnumsUserType ; utiliser IlluminateSupportFacadesSchema ; utiliser IlluminateDatabaseSchemaBlueprint ; utiliser IlluminateDatabaseMigrationsMigration ; la classe CreateUsersTable étend la migration {/** * Exécutez les migrations. * * @return void */public function up(): void{ Schema::table('users', fonction (Blueprint $table) : void {$table->bigIncrements('id');$table->timestamps();$table->enum('type', UserType :: obtenirValeurs()) ->par défaut (UserType :: Modérateur); }); } }
Vous pouvez vérifier qu'une valeur d'énumération transmise à un contrôleur est une valeur valide pour une énumération donnée à l'aide de la règle EnumValue
.
utilisez BenSampoEnumRulesEnumValue; magasin de fonctions public (Request $request) {$this->validate($request, ['user_type' => ['required', new EnumValue(UserType::class)], ]); }
Par défaut, la vérification de type est définie sur stricte, mais vous pouvez contourner cela en passant false
au deuxième paramètre facultatif de la classe EnumValue.
new EnumValue(UserType::class, false) // Désactive la vérification stricte du type.
Vous pouvez également valider des clés à l'aide de la règle EnumKey
. Ceci est utile si vous utilisez la clé enum comme paramètre d'URL pour le tri ou le filtrage par exemple.
utilisez BenSampoEnumRulesEnumKey; magasin de fonctions public (Request $request) {$this->validate($request, ['user_type' => ['required', nouveau <span class="pl-v"