Module 6 – PHP moderne (PHP 8+)
Niveau 2 – PHP avancé
Objectifs
Typage strict, union types, types nullable, attributs PHP 8, match, opérateur nullsafe, named arguments. De quoi écrire du PHP 8+ lisible et maintenable.
Théorie
Typage strict
En PHP, sans typage strict, les types sont coercés (convertis automatiquement). Exemple : une fonction qui attend un int peut recevoir la chaîne "42" et PHP la convertit en 42.
Avec declare(strict_types=1); en tête du fichier, les types doivent être respectés : passer une chaîne à une fonction qui attend un int lève une TypeError.
<?php
declare(strict_types=1);
function double(int $n): int {
return $n * 2;
}
echo double(21); // 42
double("21"); // TypeError en strict
Recommandation : mettre declare(strict_types=1); en première ligne de chaque fichier PHP pour éviter les bugs discrets dus aux conversions.
Union types (PHP 8+)
Une valeur peut être de plusieurs types. On utilise le union type avec |.
function display(int|string $v): void {
echo $v;
}
display(42); // OK
display("hi"); // OK
Nullable : on pouvait écrire ?Type (équivalent à Type|null). En PHP 8+, Type|null ou ?Type sont équivalents.
function findName(?int $id): ?string {
if ($id === null) return null;
return "User #" . $id;
}
Attributes (PHP 8)
Les attributes (attributs) permettent d’attacher des métadonnées à des classes, méthodes, propriétés ou paramètres. Ils sont lus par réflexion ou par des outils (frameworks, validateurs, ORM).
Syntaxe : #[NomAttribute] ou #[NomAttribute(args)].
#[Route(path: '/users', methods: ['GET'])]
class UserController {
#[Required]
public string $name;
}
En PHP pur (sans framework), on peut les utiliser pour marquer des contraintes et les lire avec Reflection :
#[Attribute]
class MinLength {
public function __construct(public int $value) {}
}
class User {
public function __construct(
#[MinLength(2)]
public string $firstName,
) {}
}
match (PHP 8+)
match est une expression (elle retourne une valeur). Elle remplace souvent un switch quand on associe une valeur à un résultat.
$status = 2;
$label = match ($status) {
0 => "Pending",
1 => "Approved",
2 => "Rejected",
default => "Unknown",
};
- Pas de fall-through : une seule branche est exécutée.
- default est recommandé si toutes les valeurs ne sont pas couvertes.
- Si aucune branche ne correspond et pas de default → UnhandledMatchError.
Nullsafe operator (PHP 8+)
L’opérateur ?-> appelle une méthode ou accède à une propriété seulement si l’objet n’est pas null. Sinon, toute la chaîne vaut null.
$user = getUser(); // peut retourner null
$city = $user?->getAddress()?->getCity();
// Si $user est null, $city = null (pas d’erreur).
// Si getAddress() retourne null, $city = null.
Sans nullsafe, il faudrait des conditions imbriquées ou des vérifications à chaque niveau.
Named arguments (PHP 8+)
On peut passer les arguments en les nommant, dans un ordre quelconque. Utile pour les fonctions avec beaucoup de paramètres optionnels.
function createUser(string $email, string $name = "", int $age = 0): void {
// ...
}
createUser(name: "Doe", email: "m@test.com", age: 28);
Les paramètres non nommés doivent apparaître avant les paramètres nommés.
Constructor property promotion (PHP 8)
Les paramètres du constructeur peuvent être promus en propriétés en ajoutant une visibilité :
class User {
public function __construct(
public string $email,
private string $password,
public int $age = 0,
) {}
}
Évite de déclarer les propriétés puis de les assigner manuellement dans le constructeur.
Autres évolutions utiles (PHP 8)
- throw comme expression :
$x = $value ?? throw new InvalidArgumentException('...'); - First-class callable :
$fn = strlen(...);puis$fn("hello"); - readonly (PHP 8.1) : propriété en lecture seule après initialisation.
Exemples
Exemple 1 : Typage strict + union type
<?php
declare(strict_types=1);
function parseId(int|string $id): int {
return is_int($id) ? $id : (int) $id;
}
Exemple 2 : match pour un statut
$code = 404;
$message = match ($code) {
200 => "OK",
301, 302 => "Redirect",
404 => "Not Found",
500 => "Server Error",
default => "Unknown",
};
Exemple 3 : Nullsafe
$user = $session?->getUser();
$name = $user?->getProfile()?->getDisplayName() ?? "Guest";
Bonnes pratiques
- Toujours
declare(strict_types=1);en tête de fichier. - Typer paramètres et retours (y compris union types si besoin).
- Préférer match à switch quand on retourne une valeur.
- Utiliser ?-> pour chaînes d’appels pouvant contenir null.
- Named arguments pour améliorer la lisibilité des appels complexes.
Quiz – Module 6
Q1. Que fait declare(strict_types=1); ?
Q2. Comment exprimer « int ou string » en PHP 8+ ?
Q3. Quelle est la différence entre switch et match ?
Q4. À quoi sert l’opérateur ?-> ?
Q5. Que sont les « named arguments » ?
Réponses
R1. Il active le typage strict dans le fichier : les types des paramètres et retours doivent être respectés, sinon TypeError (pas de conversion implicite).
R2. Avec un union type : int|string.
R3. match est une expression (retourne une valeur), une seule branche est exécutée (pas de fall-through), et l’absence de correspondance peut lever UnhandledMatchError sans default.
R4. Nullsafe operator : appelle méthode ou propriété seulement si l’objet n’est pas null ; sinon la chaîne vaut null (évite les erreurs sur null).
R5. Possibilité de passer les arguments en les nommant (ex. name: "Doe"), dans un ordre quelconque, pour plus de clarté.
Suite
Module 7 – Gestion des erreurs & exceptions (try/catch, exceptions personnalisées, logging).