Kodokon kodokon.com

PHP moderno: tipos estrictos, enums, match

Adopta el PHP de hoy: tipos estrictos, funciones flecha, el operador nullsafe, los enums y la expresión match.

9 min · 3 preguntas

Abrir esta lección en Kodokon

El PHP moderno abraza el tipado. declare(strict_types=1), colocado como la primera instrucción del archivo, desactiva las conversiones implícitas: pasar la cadena '10' a un parámetro float lanza un TypeError en lugar de convertirse de forma silenciosa. Tipa los parámetros y los valores de retorno: tus errores salen a la superficie pronto, en el lugar correcto, en lugar de tres archivos después.

PHP
<?php

declare(strict_types=1);

function applyDiscount(
    float $price,
    float $rate = 0.1
): float {
    return round($price * (1 - $rate), 2);
}

echo applyDiscount(49.99);
echo PHP_EOL;
echo applyDiscount(100.0, 0.25);
Una firma tipada: el contrato de la función es explícito.

Las funciones flecha fn condensan funciones anónimas de una sola expresión. Una gran ventaja sobre las clausuras clásicas: capturan automáticamente las variables del ámbito padre, sin una cláusula use. Brillan con array_map() y array_filter().

PHP
<?php

declare(strict_types=1);

$prices = [12.5, 49.9, 8.0, 120.0];
$rate = 0.2;

$discounted = array_map(
    fn (float $p): float => round($p * (1 - $rate), 2),
    $prices
);

$affordable = array_filter(
    $discounted,
    fn (float $p): bool => $p < 50
);

print_r($affordable);
La variable rate se captura sin una cláusula use.

El operador nullsafe ?-> cortocircuita una llamada en cuanto un eslabón de la cadena es null, en lugar de provocar un error fatal. Combinado con ??, reemplaza pirámides de instrucciones if por una sola línea legible.

PHP
<?php

declare(strict_types=1);

class Address
{
    public function __construct(
        public readonly string $city
    ) {
    }
}

class User
{
    public function __construct(
        public readonly ?Address $address = null
    ) {
    }
}

$alice = new User(new Address('Lyon'));
$bob = new User();

echo $alice->address?->city ?? 'Unknown city';
echo PHP_EOL;
echo $bob->address?->city ?? 'Unknown city';
Sin error para Bob: la cadena se detiene en el primer null.

Los enums dan un tipo real a conjuntos cerrados de valores (estados, roles): se vuelve imposible crear un estado inexistente. Y match es una mejora clara sobre switch: comparación estricta, un resultado devuelto como valor, y un UnhandledMatchError si ningún caso coincide - una salvaguarda contra los olvidos.

PHP
<?php

declare(strict_types=1);

enum OrderStatus: string
{
    case Pending = 'pending';
    case Shipped = 'shipped';
    case Delivered = 'delivered';

    public function label(): string
    {
        return match ($this) {
            self::Pending => 'Pending',
            self::Shipped => 'Shipped',
            self::Delivered => 'Delivered',
        };
    }
}

$status = OrderStatus::from('shipped');
echo $status->label();
Un enum respaldado por cadenas: ideal para una base de datos.

Prueba de conocimientos

Comprueba que has retenido los puntos clave de esta lección.

  1. Con declare(strict_types=1), ¿qué ocurre si pasas la cadena '10' a un parámetro de tipo float?
    • PHP convierte silenciosamente la cadena a 10.0
    • PHP emite un simple aviso y continúa
    • PHP lanza un TypeError
  2. ¿Qué distingue a una función flecha fn() de una clausura clásica function()?
    • Puede contener varias instrucciones
    • Captura automáticamente las variables del ámbito padre, sin una cláusula use
    • Se ejecuta más rápido
    • No puede declarar tipos
  3. ¿Qué ventaja tiene la expresión match sobre switch?
    • Compara de forma estricta (===), devuelve un valor y lanza un error si ningún caso coincide
    • Acepta comparaciones flexibles (==) para más flexibilidad
    • Permite la caída de un caso al siguiente