¿QUÉ ES UNA MÁQUINA DE ESTADOS EN PHP?

Una máquina de estados en PHP o State Machine es un patrón de diseño que modela el comportamiento de un objeto o sistema que puede estar en diferentes estados y solo puede pasar de un estado a otro mediante transiciones permitidas. es decir una máquina de estados en PHP es simplemente centralizar toda la lógica de “en qué estado estoy y a qué estados puedo ir” en un solo lugar, para que tu código sea más seguro, legible y fácil de mantener. Es como un semáforo:
  • Estados: Rojo → Amarillo → Verde.
  • Transiciones: Solo puede ir Rojo → Amarillo, Amarillo → Verde, Verde → Rojo. Nunca puede saltar directamente de Rojo a Verde.
En programación (y especialmente en PHP) se usa muchísimo para:
  • Estados de pedidos (Pending → Paid → Shipped → Delivered → Cancelled).
  • Flujos de videojuegos (Waiting → Joining → InProgress → Finished).
  • Workflows de usuarios (Draft → PendingReview → Approved → Published).
  • Tickets de soporte, reservas, suscripciones, etc.

¿Cómo se implementa en PHP?

La forma más limpia y recomendada hoy es usando Enums y métodos dentro del enum. Ejemplo práctico:

enum OrderStatus
{
    case Pending = 'pending';
    case Paid = 'paid';
    case Processing = 'processing';
    case Shipped = 'shipped';
    case Delivered = 'delivered';
    case Cancelled = 'cancelled';

    //Aquí se definen las transiciones permitidas
    public function canTransitionTo(self $newStatus): bool
    {
   return match ($this) {
  self::Pending     => in_array($newStatus, [self::Paid, self::Cancelled]),
  self::Paid   => in_array($newStatus, [self::Processing, self::Cancelled]),
  self::Processing  => in_array($newStatus, [self::Shipped, self::Cancelled]),
  self::Shipped     => $newStatus === self::Delivered,
  self::Delivered   => false,       // ya no se puede cambiar
  self::Cancelled   => false,
   };
    }

    // Bonus: método para aplicar el cambio
    public function transitionTo(self $newStatus): void
    {
   if (!$this->canTransitionTo($newStatus)) {
  throw new \InvalidArgumentException(
      "Transición inválida: {$this->value} → {$newStatus->value}"
  );
   }
   // aquí actualizarías el modelo
    }
}

//USO
$order = Order::find(1);
$current = OrderStatus::from($order->status);

$current->transitionTo(OrderStatus::Paid); // ✅ funciona
// $current->transitionTo(OrderStatus::Delivered); // ❌ lanza excepción