Enums (PHP 8.1)
Parte de la sección Programación Orientada a Objetos del Journey de PHP de Coddy — lección 59 de 91.
Antes de PHP 8.1, representar un conjunto fijo de valores como estados o tipos significaba usar constantes de clase o cadenas mágicas, ambos enfoques propensos a errores. Los Enums (enumeraciones) proporcionan una forma adecuada de definir un tipo que solo puede contener valores específicos y predefinidos.
Define un enum usando la palabra clave enum:
<?php
enum Status {
case Pending;
case Active;
case Completed;
}
$status = Status::Active;
echo $status->name;
Salida:
ActiveLos enums también pueden tener valores respaldados: valores de cadena o enteros asociados a cada caso. Esto es útil al almacenar enums en bases de datos o APIs:
<?php
enum Status: string {
case Pending = 'pending';
case Active = 'active';
case Completed = 'completed';
}
$status = Status::Active;
echo $status->value;
Resultado:
activeLos enums respaldados proporcionan un método from() para crear un enum a partir de su valor, y tryFrom() que devuelve null en lugar de lanzar un error para valores no válidos:
<?php
$status = Status::from('active'); // Devuelve Status::Active
$invalid = Status::tryFrom('unknown'); // Devuelve null
Los Enums también pueden contener métodos, lo que los hace potentes para encapsular lógica relacionada. Funcionan a la perfección con type hints, asegurando que tus funciones solo acepten valores válidos; ya no tendrás que comprobar si una cadena coincide con las opciones esperadas.
Desafío
FácilVamos a construir un sistema de gestión de pedidos que utiliza enums para representar los estados de los pedidos de una manera segura en cuanto a tipos. En lugar de depender de cadenas de texto que podrían estar mal escritas o ser inválidas, crearás un enum respaldado (backed enum) que mapea cada estado a un valor compatible con una base de datos.
Organizarás tu código en tres archivos:
OrderStatus.php— Crea un enum respaldado por strings llamadoOrderStatuscon cuatro casos:Pendingrespaldado por'pending'Processingrespaldado por'processing'Shippedrespaldado por'shipped'Deliveredrespaldado por'delivered'
label()que devuelva una descripción legible para los humanos para cada estado:- Pending devuelve
"Awaiting confirmation" - Processing devuelve
"Being prepared" - Shipped devuelve
"On the way" - Delivered devuelve
"Order complete"
Order.php— Crea una claseOrderque utilice el enum. Incluye el archivo OrderStatus. La clase debe:- Aceptar un ID de pedido (string) y un
OrderStatusen su constructor utilizando la promoción de propiedades del constructor - Tener un método
getInfo()que devuelva"Order [id]: [status label]" - Tener un método
getStatusValue()que devuelva el valor respaldado del estado (útil para el almacenamiento en base de datos)
- Aceptar un ID de pedido (string) y un
main.php— Incluye el archivo Order. Recibirás dos entradas: un ID de pedido y una cadena de estado (como"shipped"). UsatryFrom()para convertir de forma segura la entrada de cadena a un enumOrderStatus. Si el estado es válido, crea unOrdere imprime dos líneas:- El resultado de
getInfo() - El resultado de
getStatusValue()
"Invalid status".- El resultado de
Este desafío demuestra cómo los enums proporcionan seguridad de tipos: tu clase Order solo puede aceptar estados válidos, y el método tryFrom() te permite manejar de forma segura la entrada del usuario sin arriesgarte a valores inválidos.
Hoja de referencia
Los enums proporcionan una forma segura para los tipos de definir un conjunto fijo de valores. Define un enum utilizando la palabra clave enum:
<?php
enum Status {
case Pending;
case Active;
case Completed;
}
$status = Status::Active;
echo $status->name; // Outputs: Active
Los Backed enums asocian valores de cadena o enteros con cada caso:
<?php
enum Status: string {
case Pending = 'pending';
case Active = 'active';
case Completed = 'completed';
}
$status = Status::Active;
echo $status->value; // Outputs: active
Usa from() para crear un enum a partir de su valor, o tryFrom() que devuelve null para valores no válidos:
<?php
$status = Status::from('active'); // Returns Status::Active
$invalid = Status::tryFrom('unknown'); // Returns null
Los enums pueden contener métodos para encapsular la lógica relacionada:
<?php
enum Status: string {
case Pending = 'pending';
case Active = 'active';
public function label(): string {
return match($this) {
self::Pending => 'Awaiting',
self::Active => 'In Progress',
};
}
}
Pruébalo tú mismo
<?php
require_once 'Order.php';
// Leer la entrada
$orderId = trim(fgets(STDIN));
$statusString = trim(fgets(STDIN));
// TODO: Usar OrderStatus::tryFrom() para convertir de forma segura la cadena de estado a un enum
// tryFrom() devuelve null si el valor no es válido
// TODO: Si el estado es válido, crear un Order y mostrar:
// - El resultado de getInfo()
// - El resultado de getStatusValue()
// TODO: Si el estado no es válido, mostrar "Invalid status"
?>Esta lección incluye un breve cuestionario. Empieza la lección para responderlo y registrar tu progreso.
Todas las lecciones de Programación Orientada a Objetos
1Fundamentos de OOP
Archivos externosIntroducción a OOPClases vs ObjetosLa palabra clave $thisMétodosPropiedadesConstructor (__construct)Destructor (__destruct)Resumen - Calculadora simple4Herencia
Herencia básicaLa palabra clave parent::Sobrescritura de métodosLa palabra clave finalClases abstractasResumen - Jerarquía de empleados7Encapsulamiento
Público, Protegido, PrivadoModificadores de acceso a fondoGetters y SettersOcultamiento de informaciónPromoción de constructor (8.0)Resumen - Sistema de registros de estudiantes10Conceptos avanzados de POO
Composición vs. HerenciaInyección de dependenciasClases anónimasEnums (PHP 8.1)Fibers (PHP 8.1)Clonación de objetos a fondoGeneradores e Iteradores13Patrones de diseño Parte 2
Patrón CommandPatrón AdapterPatrón DecoratorPatrón Template MethodPatrón StatePatrón CompositePatrón Repository2Espacios de nombres y Autoloading
Introducción a los espacios de nombresLa palabra clave useEstándar de Autoloading PSR-4Autoloader de ComposerResumen - Proyecto organizado5Interfaces y Contratos
Introducción a las InterfacesImplementación de InterfacesImplementación de Múltiples InterfacesInterfaz vs Clase AbstractaType Hinting con InterfacesResumen - Calculadora de Formas8Métodos mágicos
Introducción a los métodos mágicos__toString y __debugInfo__get, __set, __isset, __unset__call y __callStatic__clone y clonación de objetos__serialize y __unserializeResumen - Colección personalizada3Propiedades de clase
Propiedades de instancia vs. estáticasConstantes en clasesMétodos y propiedades estáticosPropiedades privadas y protegidasPropiedades de solo lectura (PHP 8.1)Resumen - Gestor de cuenta bancaria6Polimorfismo
Sobrescritura de métodos revisadaPolimorfismo mediante interfacesType Hinting y tipos de uniónEnlace estático tardíoResumen - Procesador de pagos9Traits
Introducción a los TraitsUso de múltiples TraitsResolución de conflictos de TraitsMétodos abstractos en TraitsTraits frente a herencia12Patrones de diseño Parte 1
Introducción a los patrones de diseñoPatrón SingletonPatrón FactoryPatrón ObserverPatrón Strategy