Enums en PHP: cómo funcionan y ejemplos
(4 min. de lectura) Una de las novedades de versión 8.1 de php es que se añade el tipo enums (enumerados) que son un tipo de datos definido por el usuario y que consiste en un conjunto de valores posibles. De igual manera que los enum en mysql. Los enums se construyen sobre clases y objetos. Se comportan de forma similar y tienen casi los mismos requisitos. Los enums comparten los mismos espacios de nombres que las clases, las interfaces y los traits.Ejemplo declaración de enums en php:
enum tipoVehiculos
{
case Coche;
case Camion;
case Moto;
case Furgoneta;
}
//Para mostrar uno de los enums:
$vehiculo = tipoVehiculos::Coche;
var_dump(tipoVehiculos->name);
//Mostrará "Coche"
enum tipoVehiculos2: string
{
case Coche = 'Coche';
case Camion = 'Camion';
case Moto = 'Moto';
case Furgoneta = 'Furgo';
}
//Para mostrar uno de los enums:
$vehiculo = tipoVehiculos2::Furgoneta;
var_dump(tipoVehiculos->value);
//Mostrará "Furgo"
Os invito a ver los enums en mysql.
Tipos de ENUMS
// 1. Enum básico (solo nombres)
enum Status
{
case Pending;
case Approved;
case Rejected;
}
// 2. Enum Backed (el más usado - con valor)
enum OrderStatus: string
{
case Pending= 'pending';
case Paid = 'paid';
case Shipped= 'shipped';
case Delivered = 'delivered';
case Cancelled = 'cancelled';
}
// 3. Enum con valor entero
enum Role: int
{
case User = 1;
case Admin = 2;
case Super = 3;
}
//USO
$status = OrderStatus::Pending;
// Comparaciones seguras
if ($order->status === OrderStatus::Paid) { ... }
// Con base de datos (el backed value)
$order->status = OrderStatus::Shipped->value; // 'shipped'
Métodos y lógica dentro del ENUM
enum GameStatus: string
{
case Pending= 'pending';
case Joining= 'joining';
case InProgress = 'in_progress';
case Completed = 'completed';
case Cancelled = 'cancelled';
//Método para saber si se puede cambiar de estado
public function canTransitionTo(self $to): bool
{
return match ($this) {
self::Pending => in_array($to, [self::Joining, self::Cancelled]),
self::Joining => $to === self::InProgress,
self::InProgress => in_array($to, [self::Completed, self::Cancelled]),
self::Completed,
self::Cancelled=> false, // estados finales
};
}
// Método extra
public function isFinal(): bool
{
return in_array($this, [self::Completed, self::Cancelled]);
}
}
//USO
$current = GameStatus::from($game->status);
if ($current->canTransitionTo(GameStatus::Completed)) {
$game->update(['status' => GameStatus::Completed->value]);
}
Funciones útiles
- "OrderStatus::cases()" → devuelve todos los casos.
enum OrderStatus: string { case Pending= 'pending'; case Paid = 'paid'; case Shipped= 'shipped'; case Delivered = 'delivered'; case Cancelled = 'cancelled'; } $all = OrderStatus::cases(); var_dump($all); //Salida array(5) { [0] => enum(OrderStatus::Pending) [1] => enum(OrderStatus::Paid) [2] => enum(OrderStatus::Shipped) [3] => enum(OrderStatus::Delivered) [4] => enum(OrderStatus::Cancelled) - "OrderStatus::from('paid')" → convierte string a Enum.
Busca el valor (->value) y devuelve el caso correspondiente. Si el valor no existe, lanza una excepción ValueError. Ideal cuando si se está 100% seguro de que el valor es correcto.
enum OrderStatus: string { case Pending= 'pending'; case Paid = 'paid'; case Shipped= 'shipped'; case Delivered = 'delivered'; case Cancelled = 'cancelled'; } $status1 = OrderStatus::from('paid');// Funciona $status2 = OrderStatus::from('shipped'); // Funciona var_dump($status1); var_dump($status2); //Salida enum(OrderStatus::Paid) enum(OrderStatus::Shipped) // Esto lanza error: $status3 = OrderStatus::from('invalid'); // ValueError pq no existe. - "OrderStatus::tryFrom('invalid')" → null si no existe (sin excepción). Convierte string a Enum (seguro, sin error).
Es la versión segura de from(). Si el valor existe → devuelve el Enum. Si no existe → devuelve null. Recomendado cuando el dato viene de usuario, API externa, formularios, etc.
enum OrderStatus: string { case Pending= 'pending'; case Paid = 'paid'; case Shipped= 'shipped'; case Delivered = 'delivered'; case Cancelled = 'cancelled'; } $status1 = OrderStatus::tryFrom('paid'); // OrderStatus::Paid $status2 = OrderStatus::tryFrom('invalid');// null (no lanza error) pq no existe. $status3 = OrderStatus::tryFrom('shipped');// OrderStatus::Shipped var_dump($status1); var_dump($status2); var_dump($status3); //Salida enum(OrderStatus::Paid) enum(null) enum(OrderStatus::Shipped) //Ejemplo práctico: $status = OrderStatus::tryFrom($request->input('status')); if ($status === null) { abort(400, 'Estado inválido'); } - "->value" y "->name"
enum OrderStatus: string { case Pending= 'pending'; case Paid = 'paid'; case Shipped= 'shipped'; case Delivered = 'delivered'; case Cancelled = 'cancelled'; } $status = OrderStatus::Paid; echo $status->value;// El valor real (string/int) -> 'paid'. echo $status->name;// El nombre del caso ->'Paid'