Enumeradores en PHP Parte II: Valores personalizados > Blog | Josep Salvà - Desarrollo Web

La palabra de Wifft

En la primera parte vimos una introducción a los enumeradores y su uso más básico. En esta segunda parte, veremos aspectos algo más avanzados.

Por ejemplo, supongamos que tenemos que realizar una llamada a una API REST externa para mandar un objeto JSON que actualice el estado de la suscripción de cierto cliente respecto cierto servicio.

Viendo el esquema de la petición a efectuar, especificado en la documentación de dicha API, vemos que tenemos que mandar un campo llamado status_id. También aparece una correspondencia entre los posibles nombres de los estados que puede tener una suscripción (lo que ve el usuario final) y sus valores (uuid):

| Status Name      | Status Value                         |
| -----------------|--------------------------------------|
| Active           | 1fab144c-594d-4d08-ace4-b6428ec0b900 |
| Canceled         | ec9a0697-b1f9-4b51-832f-2d32b7727e37 |
| Expired          | 239add72-e737-43eb-8160-2c328bace8ba |
| Pending          | 9b858308-fa43-4d9f-ae1d-84efb505a0e6 |
| Awaiting renewal | de0217a3-1c82-4a11-972a-21b647313175 |

Entonces... ¿Cómo podemos trasladar el contenido de dicha tabla a un enum de PHP para poder interactuar fácilmente con esa información? Pues de la siguiente manera:

enum SubscriptionStatus : string
{
    case Active = '1fab144c-594d-4d08-ace4-b6428ec0b900';
    case Canceled = 'ec9a0697-b1f9-4b51-832f-2d32b7727e37';
    case Pending = '239add72-e737-43eb-8160-2c328bace8ba';
    case Expired = '9b858308-fa43-4d9f-ae1d-84efb505a0e6';
    case AwaitingRenewal = 'de0217a3-1c82-4a11-972a-21b647313175';
}

Nota: Como podemos observar en la primera línea del enum, en el caso de contener valores, podemos especificar de que tipo de datos van a ser. Se puede elegir entre int o string, pero no utilizar una unión de ambos (int|string).

Nota 2: Este tipo de enums implementan la interfaz interna BackedEnum de manera implícita, lo cual agrega dos métodos adicionales from y tryFrom. Se puede leer más detalles aquí.

Si realizamos un dump sobre el método cases() del enum, que ya vimos en la parte anterior, vemos que nos devuelve el siguiente resultado:

>>> SubscriptionStatus::cases();
[
    {
        +name: "Active",
        +value: "1fab144c-594d-4d08-ace4-b6428ec0b900", 
    },
    {
        +name: "Canceled",
        +value: "ec9a0697-b1f9-4b51-832f-2d32b7727e37", 
    },
    {
        +name: "Pending",
        +value: "239add72-e737-43eb-8160-2c328bace8ba", 
    },
    {
        +name: "Expired",
        +value: "9b858308-fa43-4d9f-ae1d-84efb505a0e6", 
    },
    {
        +name: "AwaitingRenewal",
        +value: "de0217a3-1c82-4a11-972a-21b647313175", 
    },
]

Así pues, una vez unidas todas las piezas del puzle, podemos proceder a finalizar el desarrollo. En el formulario del front-end a través del cual el usuario final podrá cambiar el estatus, se podría representar así (ejemplo de implementación a través de Blade):

<select name="status_id">
    @foreach(SubscriptionStatus::cases() as $status)
        <option value="{{ $status->value }}"
            {{ $subscription->status === $status->value ? 'selected' : null }}>
            {{ $status->name }}
        </option>
    @endforeach
</select>

En cuanto al método encargado de procesar dicho formulario, quedaría de la siguiente forma (en Laravel):

public function updateStatus(UpdateSubscriptionRequest $request, string $id) : RedirectResponse
{
    try {
        $this->makeRequest(
            endpoint: "subscription/{$id}/update-status",
            method: HttpMethod::Patch->name,
            body: json_encode(
                [
                    'subscription_id' => $request->subscription_id
                ]
            );
        );

        toast()->success(Lang::get('subscriptions::cruds.update-status.messages.success'));
    } catch (Throwable $e) {
        Log::error($e->getMessage);

        toast()->error(Lang::get('subscriptions::cruds.update-status.messages.error'));
    } finally {
        return redirect()->back();
    }
}

Lo que, por ejemplo, en caso de cancelar la suscripción, enviaría el siguiente objeto JSON:

{
    "status_id": "ec9a0697-b1f9-4b51-832f-2d32b7727e37"
}

Y eso es todo por hoy. ¡Hasta la próxima!