Aller au contenu principal

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

  1. Toujours declare(strict_types=1); en tête de fichier.
  2. Typer paramètres et retours (y compris union types si besoin).
  3. Préférer match à switch quand on retourne une valeur.
  4. Utiliser ?-> pour chaînes d’appels pouvant contenir null.
  5. 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).