Ya no se recomienda el uso de esta biblioteca, especialmente para proyectos nuevos. PHP 8.1 admite enumeraciones de forma nativa.
Véase el n.º 332.
Implementación de enumeración simple, extensible y potente para Laravel.
Pares de valores clave de enumeración como constantes de clase
Conjunto completo de métodos
Creación de instancias de enumeración
Enumeraciones marcadas/bit a bit
Escriba sugerencias
casting de atributos
Generador artesanal de enumeraciones
Reglas de validación para pasar claves o valores de enumeración como parámetros de entrada
Soporte de localización
Ampliable mediante macros
Creado por Ben Sampson
Guía
Instalación
Migrar a enumeraciones PHP nativas
Biblioteca de enumeraciones
Uso básico
Definición de enumeración
Creación de instancias
Propiedades de instancia
Conversión de instancias
Igualdad de instancias
Escriba sugerencias
Enumeración marcada/bit a bit
Casting de atributos
Migraciones
Validación
Localización
Personalización de descripciones
Personalización de la descripción de la clase
Personalización de descripciones de valores
Ampliando la clase base de Enum
Integración de Laravel Nova
Integración PHPStan
Lista de comandos artesanales
Referencia de clase de enumeración
Talones
Estás leyendo la documentación de 6.x
Si está utilizando Laravel 8, consulte los documentos de 4.x
Si está utilizando Laravel 7, consulte los documentos de 2.x
Si está utilizando Laravel 6 o inferior, consulte los documentos para 1.x
Consulte la guía de actualización para obtener información sobre cómo actualizar a la última versión.
Escribí una publicación de blog sobre el uso de laravel-enum: https://sampo.co.uk/blog/using-enums-in-laravel
Requiere PHP 8 y Laravel 9 o 10.
el compositor requiere bensampo/laravel-enum
PHP 8.1 admite enumeraciones de forma nativa. Puede migrar sus usos de BenSampoEnumEnum
a enumeraciones PHP nativas siguiendo los siguientes pasos.
Asegúrate de cumplir con los siguientes requisitos:
PHP 8.1 o superior
Laravel 10 o superior
Rector 0.17 o superior, su rector.php
incluye todos los archivos relevantes
Última versión de esta biblioteca.
Dependiendo del tamaño de su proyecto, puede optar por migrar todas las enumeraciones a la vez o migrar solo un par o una enumeración a la vez.
Convierta todas las enumeraciones a la vez: php artisan enum:to-native
Pase el nombre de clase completo de una enumeración para limitar la conversión: php artisan enum:to-native "AppEnumsUserType"
Esto es necesario si se utilizan enumeraciones durante la fase de arranque de Laravel, la conversión de sus usos interfiere con Larastan e impide que funcione una segunda ejecución de Rector.
Revise y valide los cambios de código para casos extremos omitidos:
Ver no implementado
Enum::coerce()
: si solo se pasaron valores, puede reemplazarlo con tryFrom()
. Si también se pueden pasar claves o instancias, es posible que necesite lógica adicional para cubrir esto.
Enum::$description
y Enum::getDescription()
: implementa una alternativa.
bloques try/catch que manejan BenSampoEnumExceptionsInvalidEnumKeyException
o BenSampoEnumExceptionsInvalidEnumMemberException
. Detecte el ValueError
arrojado por enumeraciones nativas o cambie a tryFrom()
y maneje null
.
Una vez que se hayan convertido todas las enumeraciones, puede eliminar su dependencia de esta biblioteca.
Explore y descargue desde una lista de enumeraciones aportadas por la comunidad de uso común.
Biblioteca de enumeración →
Puede utilizar el siguiente comando Artisan para generar una nueva clase de enumeración:
php artesano hacer:enum Tipo de usuario
Ahora, sólo necesitas agregar los posibles valores que tu enumeración puede tener como constantes.
<?php declara(strict_types=1);espacio de nombres AppEnums;usa BenSampoEnumEnum;la clase final UserType extiende Enum {const Administrador = 0;const Moderador = 1;const Suscriptor = 2;const SuperAdministrador = 3; }
¡Eso es todo! Tenga en cuenta que debido a que los valores de enumeración se definen como constantes simples, puede acceder a ellos simplemente como cualquier otra constante de clase.
UserType::Administrator // Tiene un valor de 0
Puede resultar útil crear instancias de enumeraciones para pasarlas entre funciones con la ventaja de las sugerencias de tipo.
Además, es imposible crear una instancia de una enumeración con un valor no válido, por lo tanto, puede estar seguro de que el valor pasado siempre es válido.
Por conveniencia, se pueden crear instancias de enumeraciones de varias maneras:
// Nueva clase PHP estándar, pasando el valor de enumeración deseado como parámetro$enumInstance = new UserType(UserType::Administrator);// Igual que el constructor, instanciado por valor$enumInstance = UserType::fromValue(UserType::Administrator) ;// Utilice una clave de enumeración en lugar de su valor$enumInstance = UserType::fromKey('Administrator');// Llamando estáticamente al nombre de la clave como método, utilizando __callStatic magic$enumInstance = UserType::Administrator();// Intenta crear una instancia de una nueva enumeración utilizando la clave o valor proporcionado. Devuelve nulo si no se puede crear una instancia de Enum.$enumInstance = UserType::coerce($someValue);
Si desea que su IDE complete automáticamente los asistentes de creación de instancias estáticas, puede generar anotaciones PHPDoc mediante un comando artesanal.
De forma predeterminada, se anotarán todas las enumeraciones en app/Enums
(puede cambiar la carpeta pasando una ruta a --folder
).
enumeración artesanal de php: anotar
Puede anotar una sola clase especificando el nombre de la clase.
enumeración artesanal de php: anotar "AppEnumsUserType"
Una vez que tenga una instancia de enumeración, puede acceder a la key
, value
y description
como propiedades.
$userType = UserType::fromValue(UserType::SuperAdministrator);$userType->key; // SuperAdministrador$tipodeusuario->valor; // 3$tipo de usuario->descripción; // superadministrador
Esto es particularmente útil si pasa una instancia de enumeración a una vista Blade.
Las instancias de enumeración se pueden convertir en cadenas a medida que implementan el método mágico __toString()
.
Esto también significa que se pueden reproducir, por ejemplo, en vistas de palas.
$userType = UserType::fromValue(UserType::SuperAdministrator); (cadena) $tipo de usuario // '3'
Puede verificar la igualdad de una instancia con cualquier valor pasándolo al método is
. Por conveniencia, también existe un método isNot
que es exactamente lo contrario del método is
.
$admin = Tipo de Usuario::Administrador();$admin->is(Tipo de Usuario::Administrador); // verdadero$admin->is($admin); // verdadero$admin->is(UserType::Administrator()); // verdadero$admin->is(UserType::Moderador); // false$admin->is(UserType::Moderador()); // false$admin->is('valor-aleatorio'); // FALSO
También puede verificar si el valor de la instancia coincide con una matriz de valores posibles usando el método in
y usar notIn
para verificar si el valor de la instancia no está en una matriz de valores. Los iterables también se pueden comparar.
$admin = Tipo de usuario::Administrador();$admin->in([Tipo de usuario::Moderador, Tipo de usuario::Administrador]); // true$admin->in([Tipo de usuario::Moderador(), Tipo de usuario::Administrador()]); // true$admin->in([Tipo de usuario::Moderador, Tipo de usuario::Suscriptor]); // false$admin->in(['valor-aleatorio']); // false$admin->notIn([Tipo de usuario::Moderador, Tipo de usuario::Administrador]); // false$admin->notIn([Tipo de usuario::Moderador(), Tipo de usuario::Administrador()]); // false$admin->notIn([Tipo de usuario::Moderador, Tipo de usuario::Suscriptor]); // verdadero$admin->notIn(['valor-aleatorio']); // verdadero
Las enumeraciones instanciadas no son singletons, sino que se crea un nuevo objeto cada vez. Por lo tanto, la comparación estricta ===
de diferentes instancias de enumeración siempre devolverá false
, sin importar el valor. Por el contrario, la comparación flexible ==
dependerá del valor.
$admin = Tipo de Usuario::Administrador();$admin === Tipo de Usuario::Administrador(); // falseUserType::Administrator() === UserType::Administrator(); // false$admin === Tipo de usuario::Moderador(); // falso$admin === $admin; // verdadero$admin == Tipo de usuario::Administrador(); // verdadero$admin == Tipo de usuario::Administrador; // verdadero$admin == Tipo de usuario::Moderador(); // false$admin == Tipo de usuario::Moderador; // FALSO
Uno de los beneficios de las instancias de enumeración es que le permite utilizar sugerencias de tipos, como se muestra a continuación.
función canPerformAction(Tipo de usuario $Tipo de usuario) {if ($userType->is(UserType::SuperAdministrator)) {devuelve verdadero; }devuelve falso; }$userType1 = UserType::fromValue(UserType::SuperAdministrator);$userType2 = UserType::fromValue(UserType::Moderator);canPerformAction($userType1); // Devuelve truecanPerformAction($userType2); // Devuelve falso
Las enumeraciones estándar representan un único valor a la vez, pero las enumeraciones marcadas o bit a bit son capaces de representar múltiples valores simultáneamente. Esto los hace perfectos para cuando desea expresar múltiples selecciones de un conjunto limitado de opciones. Un buen ejemplo de esto serían los permisos de usuario donde hay un número limitado de permisos posibles pero un usuario puede tener ninguno, algunos o todos ellos.
Puede crear una enumeración marcada utilizando el siguiente comando artesanal:
php artisan make:enum UserPermissions --flagged
Al definir valores, debe usar potencias de 2, la forma más sencilla de hacerlo es utilizando el operador de desplazamiento a la izquierda <<
de esta manera:
La clase final UserPermissions extiende FlaggedEnum {const ReadComments = 1 << 0;const WriteComments = 1 << 1;const EditComments = 1 << 2;const DeleteComments = 1 << 3;// El siguiente sería `1 << 4` y así sucesivamente. ..}
Puede utilizar bit a bit o |
para establecer un valor de acceso directo que represente un conjunto determinado de valores.
La clase final UserPermissions extiende FlaggedEnum {const ReadComments = 1 << 0;const WriteComments = 1 << 1;const EditComments = 1 << 2;const DeleteComments = 1 << 3;// Accesos directosconst Member = self::ReadComments | self::EscribirComentarios; // Leer y escribir.const Moderador = self::Miembro | self::EditarComentarios; // Todos los permisos que tiene un miembro, más Edit.const Admin = self::Moderator | self::EliminarComentarios; // Todos los permisos que tiene un Moderador, más Eliminar.}
Hay un par de formas de crear una instancia de una enumeración marcada:
// Nueva clase PHP estándar, pasando los valores de enumeración deseados como una matriz de valores o una matriz de instancias de enumeración$permissions = new UserPermissions([UserPermissions::ReadComments, UserPermissions::EditComments]);$permissions = new UserPermissions([UserPermissions: :ReadComments(), UserPermissions::EditComments()]);// Método de banderas estáticas, pasando nuevamente los valores de enumeración deseados como una matriz de valores o una matriz de instancias de enumeración$permisos = UserPermissions::flags([UserPermissions::ReadComments, UserPermissions::EditComments]);$permissions = UserPermissions::flags([UserPermissions::ReadComments(), UserPermissions::EditComments()]);
La conversión de atributos funciona de la misma manera que las enumeraciones de valor único.
Las enumeraciones marcadas no pueden contener ningún valor. Cada enumeración marcada tiene una constante predefinida de None
que es comparable a 0
.
Permisos de usuario::flags([])->valor === Permisos de usuario::Ninguno; // Verdadero
Además de los métodos de enumeración estándar, hay un conjunto de métodos útiles disponibles en enumeraciones marcadas.
Nota: En cualquier lugar donde se pase una propiedad estática, también se puede pasar una instancia de enumeración.
Establezca los indicadores para la enumeración en la matriz de indicadores dada.
$permisos = UserPermissions::flags([UserPermissions::ReadComments]);$permissions->flags([UserPermissions::EditComments, UserPermissions::DeleteComments]); // Las banderas ahora son: Editar comentarios, Eliminar comentarios.
Agregue la bandera dada a la enumeración
$permisos = UserPermissions::flags([UserPermissions::ReadComments]);$permissions->addFlag(UserPermissions::EditComments); // Las banderas ahora son: LeerComentarios, EditarComentarios.
Agregue las banderas dadas a la enumeración.
$permisos = UserPermissions::flags([UserPermissions::ReadComments]);$permissions->addFlags([UserPermissions::EditComments, UserPermissions::WriteComments]); // Las banderas ahora son: LeerComentarios, EditarComentarios, EscribirComentarios.
Agregar todas las banderas a la enumeración
$permisos = UserPermissions::flags([UserPermissions::ReadComments]);$permissions->addAllFlags(); // Enum ahora tiene todas las banderas
Eliminar la bandera dada de la enumeración
$permisos = UserPermissions::flags([UserPermissions::ReadComments, UserPermissions::WriteComments]);$permissions->removeFlag(UserPermissions::ReadComments); // Las banderas ahora son: WriteComments.
Eliminar las banderas dadas de la enumeración.
$permisos = UserPermissions::flags([UserPermissions::ReadComments, UserPermissions::WriteComments, UserPermissions::EditComments]);$permissions->removeFlags([UserPermissions::ReadComments, UserPermissions::WriteComments]); // Las banderas ahora son: EditComments.
Eliminar todas las banderas de la enumeración
$permisos = UserPermissions::flags([UserPermissions::ReadComments, UserPermissions::WriteComments]);$permissions->removeAllFlags();
Compruebe si la enumeración tiene el indicador especificado.
$permisos = UserPermissions::flags([UserPermissions::ReadComments, UserPermissions::WriteComments]);$permissions->hasFlag(UserPermissions::ReadComments); // True$permisos->hasFlag(UserPermissions::EditComments); // FALSO
Compruebe si la enumeración tiene todos los indicadores especificados.
$permisos = UserPermissions::flags([UserPermissions::ReadComments, UserPermissions::WriteComments]);$permissions->hasFlags([UserPermissions::ReadComments, UserPermissions::WriteComments]); // True$permissions->hasFlags([UserPermissions::ReadComments, UserPermissions::EditComments]); // FALSO
Compruebe si la enumeración no tiene el indicador especificado.
$permisos = UserPermissions::flags([UserPermissions::ReadComments, UserPermissions::WriteComments]);$permissions->notHasFlag(UserPermissions::EditComments); // True$permisos->notHasFlag(UserPermissions::ReadComments); // FALSO
Compruebe si la enumeración no tiene ninguno de los indicadores especificados.
$permisos = UserPermissions::flags([UserPermissions::ReadComments, UserPermissions::WriteComments]);$permissions->notHasFlags([UserPermissions::ReadComments, UserPermissions::EditComments]); // True$permissions->notHasFlags([UserPermissions::ReadComments, UserPermissions::WriteComments]); // FALSO
Devuelve las banderas como una matriz de instancias.
$permisos = UserPermissions::flags([UserPermissions::ReadComments, UserPermissions::WriteComments]);$permissions->getFlags(); // [Permisos de usuario::ReadComments(), Permisos de usuario::WriteComments()];
Compruebe si hay varios indicadores configurados en la enumeración.
$permisos = UserPermissions::flags([UserPermissions::ReadComments, UserPermissions::WriteComments]);$permissions->hasMultipleFlags(); // Verdadero;$permisos->removeFlag(UserPermissions::ReadComments)->hasMultipleFlags(); // FALSO
Obtenga la máscara de bits para la enumeración.
Permisos de usuario::Miembro()->getBitmask(); // 11;Permisos de usuario::Moderador()->getBitmask(); // 111;Permisos de usuario::Admin()->getBitmask(); // 1111;Permisos de usuario::DeleteComments()->getBitmask(); // 1000;
Para usar enumeraciones marcadas directamente en sus consultas de Eloquent, puede usar el rasgo QueriesFlaggedEnums
en su modelo, que le proporciona los siguientes métodos:
Usuario::hasFlag('permisos', UserPermissions::DeleteComments())->get();
Usuario::notHasFlag('permisos', UserPermissions::DeleteComments())->get();
Usuario::hasAllFlags('permisos', [UserPermissions::EditComment(), UserPermissions::ReadComment()])->get();
Usuario::hasAnyFlags('permisos', [Permisos de usuario::DeleteComments(), Permisos de usuario::EditComments()])->get();
Puede transmitir atributos de modelo a enumeraciones utilizando la conversión personalizada integrada de Laravel. Esto convertirá el atributo a una instancia de enumeración al obtenerlo y volverá al valor de enumeración al configurarlo. Dado que Enum::class
implementa el contrato Castable
, solo necesitas especificar el nombre de clase de la enumeración:
use BenSampoEnumTestsEnumsUserType;use IlluminateDatabaseEloquentModel;el ejemplo de clase extiende el modelo {protected $casts = ['random_flag' => 'boolean', // Ejemplo estándar laravel cast'user_type' => UserType::class, // Ejemplo enum cast]; }
Ahora, cuando acceda al atributo user_type
de su modelo Example
, el valor subyacente se devolverá como una enumeración UserType
.
$ejemplo = Ejemplo::first();$ejemplo->tipo_usuario // Instancia de tipo de usuario
Revise los métodos y propiedades disponibles en instancias de enumeración para aprovechar al máximo la conversión de atributos.
Puede establecer el valor pasando el valor de enumeración u otra instancia de enumeración.
$ejemplo = Ejemplo::first();// Establecer usando el valor de enumeración$ejemplo->user_type = UserType::Moderator;// Establecer usando enum instancia$ejemplo->user_type = UserType::Moderator();
$model->toArray()
Al usar toArray
(o devolver modelo/modelos de su controlador como respuesta), Laravel llamará al método toArray
en la instancia de enumeración.
De forma predeterminada, esto devolverá sólo el valor en su tipo nativo. Es posible que también desee tener acceso a otras propiedades (clave, descripción), por ejemplo, para volver a la aplicación JavaScript.
Para personalizar este comportamiento, puede anular el método toArray
en la instancia de enumeración.
// Ejemplo Enumfinal clase UserType extiende Enum {const ADMINISTRADOR = 0;const MODERADOR = 1; }$instancia = Tipo de usuario::Moderador();// Función pública predeterminada toArray() {return $this->valor; }// Devuelve int(1)// Devuelve todas las propiedades de la función pública a Array() {devolver $esto; }// Devuelve una matriz de todas las propiedades// array(3) {// ["value"]=>// int(1)"// ["key"]=>// string(9) "MODERATOR "// ["descripción"]=>// string(9) "Moderador"// }
Muchas bases de datos devuelven todo como cadenas (por ejemplo, se puede devolver un número entero como la cadena '1'
). Para reducir la fricción para los usuarios de la biblioteca, utilizamos coerción de tipos para determinar el valor previsto. Si prefieres controlar esto, puedes anular el método estático parseDatabase
en tu clase de enumeración:
La clase final UserType extiende Enum {Administrador constante = 0; Moderador constante = 1; función estática pública parseDatabase ($ valor) {retorno (int) $valor; } }
Devolver null
desde el método parseDatabase
hará que el atributo en el modelo también sea null
. Esto puede resultar útil si su base de datos almacena valores en blanco inconsistentes, como cadenas vacías en lugar de NULL
.
Si está transmitiendo atributos de su modelo a enumeraciones, el paquete laravel-ide-helper se puede utilizar para generar automáticamente bloques de documentos de propiedades.
Debido a que las enumeraciones imponen coherencia a nivel de código, no es necesario volver a hacerlo a nivel de base de datos; por lo tanto, el tipo recomendado para las columnas de la base de datos es string
o int
, según los valores de enumeración. Esto significa que puede agregar/eliminar valores de enumeración en su código sin preocuparse por la capa de su base de datos.
use AppEnumsUserType; use IlluminateSupportFacadesSchema; use IlluminateDatabaseSchemaBlueprint; use IlluminateDatabaseMigrationsMigration; la clase CreateUsersTable extiende la migración {/** * Ejecutar las migraciones. * * @return void */función pública arriba(): void{ Esquema::table('usuarios', función (Blueprint $table): void {$table->bigIncrements('id');$table->timestamps();$table->string('tipo') ->predeterminado(Tipo de usuario::Moderador); }); } }
enum
Alternativamente, puede utilizar clases Enum
en sus migraciones para definir columnas de enumeración. Los valores de enumeración deben definirse como cadenas.
use AppEnumsUserType; use IlluminateSupportFacadesSchema; use IlluminateDatabaseSchemaBlueprint; use IlluminateDatabaseMigrationsMigration; la clase CreateUsersTable extiende la migración {/** * Ejecutar las migraciones. * * @return void */función pública arriba(): void{ Schema::table('usuarios', función (Blueprint $table): void {$table->bigIncrements('id');$table->timestamps();$table->enum('type', UserType:: obtenerValores()) ->predeterminado(Tipo de usuario::Moderador); }); } }
Puede validar que un valor de enumeración pasado a un controlador sea un valor válido para una enumeración determinada utilizando la regla EnumValue
.
utilizar BenSampoEnumRulesEnumValue; almacén de funciones públicas (Solicitud $solicitud) {$this->validate($request, ['user_type' => ['required', new EnumValue(UserType::class)], ]); }
De forma predeterminada, la verificación de tipos está configurada como estricta, pero puede evitarla pasando false
al segundo parámetro opcional de la clase EnumValue.
new EnumValue(UserType::class, false) // Desactiva la verificación estricta de tipos.
También puede validar claves utilizando la regla EnumKey
. Esto es útil si toma la clave de enumeración como parámetro de URL para ordenar o filtrar, por ejemplo.
utilizar BenSampoEnumRulesEnumKey; almacén de funciones públicas (Solicitud $solicitud) {$this->validate($solicitud, ['user_type' => ['requerido', nuevo <span class="pl-v"