Adopta el PHP de hoy: tipos estrictos, funciones flecha, el operador nullsafe, los enums y la expresión match.
Abrir esta lección en KodokonEl 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
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);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
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);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
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';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
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();