Menu
Coddy logo textTech

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:

Active

Los 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:

active

Los 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.

challenge icon

Desafío

Fácil

Vamos 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 llamado OrderStatus con cuatro casos:
    • Pending respaldado por 'pending'
    • Processing respaldado por 'processing'
    • Shipped respaldado por 'shipped'
    • Delivered respaldado por 'delivered'
    Añade un método 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 clase Order que utilice el enum. Incluye el archivo OrderStatus. La clase debe:
    • Aceptar un ID de pedido (string) y un OrderStatus en 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)
  • main.php — Incluye el archivo Order. Recibirás dos entradas: un ID de pedido y una cadena de estado (como "shipped"). Usa tryFrom() para convertir de forma segura la entrada de cadena a un enum OrderStatus. Si el estado es válido, crea un Order e imprime dos líneas:
    • El resultado de getInfo()
    • El resultado de getStatusValue()
    Si la cadena de estado no es válida, imprime "Invalid status".

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"

?>
quiz iconPonte a prueba

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