Kodokon kodokon.com

PHP moderne : types stricts, enums, match

Adoptez le PHP d'aujourd'hui : types stricts, fonctions fléchées, opérateur nullsafe, enums et expression match.

9 min · 3 questions

Ouvrir cette leçon dans Kodokon

PHP moderne assume le typage. declare(strict_types=1), placé en première instruction du fichier, désactive les conversions implicites : passer la chaîne '10' à un paramètre float lève une TypeError au lieu d'être converti en silence. Typez paramètres et valeurs de retour : vos erreurs éclatent tôt, au bon endroit, plutôt que trois fichiers plus loin.

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);
Signature typée : le contrat de la fonction est explicite.

Les fonctions fléchées fn condensent les fonctions anonymes d'une seule expression. Grand avantage sur les closures classiques : elles capturent automatiquement les variables du contexte parent, sans clause use. Elles brillent avec array_map() et 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 est capturée sans clause use.

L'opérateur nullsafe ?-> court-circuite un appel dès qu'un maillon de la chaîne vaut null, au lieu de provoquer une erreur fatale. Combiné à ??, il remplace des pyramides de if par une seule ligne lisible.

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 ?? 'Ville inconnue';
echo PHP_EOL;
echo $bob->address?->city ?? 'Ville inconnue';
Aucune erreur pour Bob : la chaîne s'arrête au premier null.

Les enums donnent un vrai type aux ensembles fermés de valeurs (statuts, rôles) : impossible de créer un statut inexistant. Et match remplace avantageusement switch : comparaison stricte, résultat renvoyé comme valeur, et une UnhandledMatchError si aucun cas ne correspond - un garde-fou contre les oublis.

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 => 'En attente',
            self::Shipped => 'Expédiée',
            self::Delivered => 'Livrée',
        };
    }
}

$status = OrderStatus::from('shipped');
echo $status->label();
Enum adossé à des chaînes : idéal pour une base de données.

Quiz de validation

Vérifiez que vous avez bien retenu les points clés de cette leçon.

  1. Avec declare(strict_types=1), que se passe-t-il si vous passez la chaîne '10' à un paramètre typé float ?
    • PHP convertit silencieusement la chaîne en 10.0
    • PHP émet un simple avertissement et continue
    • PHP lève une TypeError
  2. Qu'est-ce qui distingue une fonction fléchée fn() d'une closure classique function() ?
    • Elle peut contenir plusieurs instructions
    • Elle capture automatiquement les variables du contexte parent, sans clause use
    • Elle s'exécute plus vite
    • Elle ne peut pas déclarer de types
  3. Quel avantage l'expression match a-t-elle sur switch ?
    • Elle compare en strict (===), renvoie une valeur et lève une erreur si aucun cas ne correspond
    • Elle accepte les comparaisons larges (==) pour plus de souplesse
    • Elle autorise le passage d'un cas au suivant (fall-through)