Le monde PHP accueille sa version 8.5 avec une fonctionnalité qui va changer la façon d'écrire du code : le pipe operator. Inspiré de langages comme Elixir ou JavaScript, cet opérateur |> permet enfin de chaîner les fonctions de manière lisible, de gauche à droite, comme on lit naturellement.
Mais PHP 8.5 ne s'arrête pas là: cette nouvelle version introduit également des fonctions de manipulation de tableaux attendues depuis des années, la possibilité d'utiliser des closures dans les expressions constantes, et un nouvel attribut pour prévenir les oublis critiques.
Ces ajouts ne bouleversent pas le langage, ils le raffinent. Ils éliminent les irritants du quotidien et offrent aux développeurs des outils plus expressifs.
PHP 8.5 continue de mûrir intelligemment.
Le pipe operator : la fin des parenthèses de l'enfer
Le pipe operator |> permet de chaîner des fonctions de manière lisible de gauche à droite.
// Avant PHP 8.5 : lisez de l'intérieur vers l'extérieur
$result = array_sum(
array_map(
fn($x) => $x * 2,
array_filter(
$numbers,
fn($x) => $x > 10
)
)
);
// Avec PHP 8.5 : lisez de gauche à droite
$result = $numbers
|> array_filter(fn($x) => $x > 10, ...)
|> array_map(fn($x) => $x * 2, ...)
|> array_sum(...);
Le ... indique où placer le résultat précédent. De cette manière, la syntaxe est claire et plus facile à lire car on évite les imbrications qui font du bruit inutiliement dans la lecture.
// Transformation de données complexes
$output = $userData
|> json_decode(...)
|> validateUser(...)
|> enrichWithMetadata(...)
|> formatForApi(...)
|> json_encode(...);
// Traitement de chaînes
$slug = $title
|> strtolower(...)
|> str_replace(' ', '-', ...)
|> preg_replace('/[^a-z0-9-]/', '', ...)
|> trim(..., '-');
Enfin deux fonctions évidentes pour les tableaux
PHP avait reset() et end() qui modifiaient le pointeur interne du tableau. Personne n'aimait ça. PHP 8.5 ajoute array_first() et array_last(). Simples. Prévisibles. Sans effets de bord.
$users = ['Alice', 'Bob', 'Charlie', 'Diana'];
// Avant : manipulation du pointeur interne
reset($users);
$first = current($users); // 'Alice'
end($users);
$last = current($users); // 'Diana'
reset($users); // N'oubliez pas de réinitialiser
// PHP 8.5 : direct
$first = array_first($users); // 'Alice'
$last = array_last($users); // 'Diana'
// Avec un callback pour filtrer
$numbers = [1, 2, 3, 4, 5, 6];
$firstEven = array_first($numbers, fn($n) => $n % 2 === 0); // 2
$lastOdd = array_last($numbers, fn($n) => $n % 2 !== 0); // 5
// Tableau vide : retourne null
$empty = [];
$result = array_first($empty); // null
Closures dans les expressions constantes
PHP 8.5 permet d'utiliser des closures dans les expressions constantes. Les attributs, les valeurs par défaut de paramètres, les constantes de classe peuvent maintenant contenir des fonctions anonymes.
// Attributs avec closures
class UserController {
#[Route('/users', middleware: fn() => new AuthMiddleware())]
public function index() {}
#[Validate(rules: [
'email' => fn($value) => filter_var($value, FILTER_VALIDATE_EMAIL)
])]
public function create() {}
}
// Valeurs par défaut avec closures
class QueryBuilder {
public function __construct(
private array $transformers = [
'uppercase' => fn($v) => strtoupper($v),
'lowercase' => fn($v) => strtolower($v),
]
) {}
}
// Constantes de classe avec closures
class Calculator {
public const OPERATIONS = [
'add' => fn($a, $b) => $a + $b,
'multiply' => fn($a, $b) => $a * $b,
'power' => fn($a, $b) => $a ** $b,
];
}
$result = Calculator::OPERATIONS['multiply'](5, 3); // 15
Cette fonctionnalité ouvre des possibilités pour les frameworks. Les systèmes de validation. Les configurations complexes. Tout ce qui nécessitait auparavant des workarounds.
Protégez vos valeurs de retour critiques
L'attribut #[NoDiscard] avertit quand une valeur de retour importante est ignorée. Pour les fonctions où oublier le résultat est une erreur.
class Database {
#[NoDiscard]
public function beginTransaction(): Transaction {
return new Transaction($this->pdo);
}
#[NoDiscard]
public function prepare(string $query): Statement {
return new Statement($this->pdo->prepare($query));
}
}
$db = new Database();
// Erreur : valeur de retour ignorée
$db->beginTransaction(); // Warning: Result of beginTransaction() should not be discarded
// Correct : valeur utilisée
$transaction = $db->beginTransaction();
$transaction->commit();
// Cas pratique : constructeur d'objets immutables
class Config {
#[NoDiscard]
public function withOption(string $key, mixed $value): self {
$new = clone $this;
$new->options[$key] = $value;
return $new;
}
}
$config = new Config();
$config->withOption('debug', true); // Warning: nouvelle instance ignorée
// Correct
$config = $config->withOption('debug', true);
Compositions complexes
Le pipe operator brille dans les transformations de données complexes.
// Pipeline de traitement d'image (conceptuel)
$processedImage = $uploadedFile
|> validateImageFormat(...)
|> resize(..., 800, 600)
|> applyWatermark(..., $logo)
|> optimize(...)
|> saveToStorage(...);
// Analyse de logs
$criticalErrors = $logFile
|> file_get_contents(...)
|> explode("\n", ...)
|> array_filter(fn($line) => str_contains($line, 'ERROR'), ...)
|> array_map(fn($line) => parseLogLine($line), ...)
|> array_filter(fn($entry) => $entry['severity'] === 'CRITICAL', ...)
|> array_values(...);
// API REST avec transformation
$response = $request
|> extractPayload(...)
|> validateSchema(..., $schema)
|> sanitizeInput(...)
|> processBusinessLogic(...)
|> formatResponse(...)
|> json_encode(...);
Combinaison des nouvelles fonctionnalités
PHP 8.5 permet de combiner ces fonctionnalités pour un code plus expressif.
class DataProcessor {
#[NoDiscard]
public function process(array $data): Result {
return $data
|> array_filter(fn($item) => $item['valid'], ...)
|> array_map(fn($item) => $this->transform($item), ...)
|> fn($items) => new Result(
first: array_first($items),
last: array_last($items),
all: $items
);
}
private const TRANSFORMERS = [
'normalize' => fn($v) => strtolower(trim($v)),
'capitalize' => fn($v) => ucfirst($v),
];
}
// Utilisation
$processor = new DataProcessor();
$result = $processor->process($rawData); // #[NoDiscard] force l'utilisation
$firstItem = $result->first; // array_first() sous le capot
$lastItem = $result->last; // array_last() sous le capot
Le mot de la fin
PHP 8.5 s'inscrit dans la lignée des versions récentes qui ont transformé le langage en profondeur. Avec le pipe operator, PHP rattrape son retard sur les langages fonctionnels et offre enfin une syntaxe élégante pour le chaînage de fonctions. Les ajouts comme array_first() et array_last() peuvent sembler anecdotiques, mais ils corrigent des lacunes historiques qui forçaient les développeurs à utiliser des solutions bancales. Les closures dans les expressions constantes débloquent de nouvelles possibilités architecturales, tandis que #[NoDiscard] renforce la sécurité du code en prévenant des erreurs silencieuses.
Cette version illustre parfaitement la philosophie actuelle de PHP : moderniser la façon de coder sans tout brusquer ce qui rend le code plus maintenable et plus lisible.
Les développeurs qui ont suivi l'évolution de PHP depuis la version 7 reconnaissent le chemin parcouru. PHP 8.5 n'est qu'une étape supplémentaire, mais elle confirme que le langage a trouvé son rythme en embrassant les partiques modernes de développement.